diff --git a/src/shrpx_downstream.cc b/src/shrpx_downstream.cc index e97e2913..54c29fcc 100644 --- a/src/shrpx_downstream.cc +++ b/src/shrpx_downstream.cc @@ -152,10 +152,6 @@ Downstream::~Downstream() { DLOG(INFO, this) << "Deleting"; } - if (blocked_link_) { - detach_blocked_link(blocked_link_); - } - // check nullptr for unittest if (upstream_) { auto loop = upstream_->get_client_handler()->get_loop(); @@ -1200,12 +1196,10 @@ void Downstream::attach_blocked_link(BlockedLink *l) { blocked_link_ = l; } -void Downstream::detach_blocked_link(BlockedLink *l) { - assert(blocked_link_); - assert(l->downstream == this); - - l->downstream = nullptr; +BlockedLink *Downstream::detach_blocked_link() { + auto link = blocked_link_; blocked_link_ = nullptr; + return link; } void Downstream::add_request_headers_sum(size_t amount) { diff --git a/src/shrpx_downstream.h b/src/shrpx_downstream.h index f0edeb2c..1294c0bd 100644 --- a/src/shrpx_downstream.h +++ b/src/shrpx_downstream.h @@ -332,7 +332,7 @@ public: void set_dispatch_state(int s); void attach_blocked_link(BlockedLink *l); - void detach_blocked_link(BlockedLink *l); + BlockedLink *detach_blocked_link(); enum { EVENT_ERROR = 0x1, diff --git a/src/shrpx_downstream_queue.cc b/src/shrpx_downstream_queue.cc index fa2ba517..0462d2a7 100644 --- a/src/shrpx_downstream_queue.cc +++ b/src/shrpx_downstream_queue.cc @@ -131,6 +131,12 @@ Downstream *DownstreamQueue::remove_and_get_blocked(Downstream *downstream) { if (downstream->get_dispatch_state() == Downstream::DISPATCH_ACTIVE) { --ent.num_active; + } else { + auto link = downstream->detach_blocked_link(); + if (link) { + ent.blocked.remove(link); + delete link; + } } if (remove_host_entry_if_empty(ent, host_entries_, host)) { @@ -141,24 +147,19 @@ Downstream *DownstreamQueue::remove_and_get_blocked(Downstream *downstream) { return nullptr; } - for (auto link = ent.blocked.head; link;) { - auto next = link->dlnext; - if (!link->downstream) { - // If non-active (e.g., pending) Downstream got deleted, - // link->downstream is nullptr. - ent.blocked.remove(link); - delete link; - link = next; - continue; - } - auto next_downstream = link->downstream; - next_downstream->detach_blocked_link(link); - ent.blocked.remove(link); - delete link; - remove_host_entry_if_empty(ent, host_entries_, host); - return next_downstream; + auto link = ent.blocked.head; + + if (!link) { + return nullptr; } - return nullptr; + + auto next_downstream = link->downstream; + next_downstream->detach_blocked_link(); + ent.blocked.remove(link); + delete link; + remove_host_entry_if_empty(ent, host_entries_, host); + + return next_downstream; } Downstream *DownstreamQueue::get_downstreams() const {