Loading src/httpd.cpp +46 −6 Changes for src/httpd.cpp: 46 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -924,11 +924,15 @@ void libhttppp::HttpEvent::_resumeH2Streams(HttpRequest &cureq, cureq.h2state().peerStreamWindows.erase(sid); streams.erase(it); } else { // Signal the main connection so the epoll loop // re-arms with EPOLLOUT and calls ResponseEvent, // which will resume this stream without waiting // for the client to send WINDOW_UPDATE. cureq.slots[0].ResponsePending.store(true, std::memory_order_release); // Signal and explicitly re-arm the real H2 connection. // The synthetic per-stream request is not registered in // epoll, therefore setting only ResponsePending is not // sufficient to wake the connection again. cureq.slots[0].ResponsePending.store( true, std::memory_order_release ); netplus::requestWritablePoll(cureq); } break; // Don't busy-loop; wait for next event } Loading Loading @@ -1924,7 +1928,43 @@ void libhttppp::HttpEvent::ResponseEvent(netplus::con &curcon,const int tid,ULON // DATA generated above must be handed to the socket now. If the // socket is temporarily blocked, _flushSendDataNow() re-arms the // writable event so the response cannot remain parked forever. _flushSendDataNow(cureq); const bool fullyFlushed = _flushSendDataNow(cureq); /* * _flushSendDataNow() clears ResponsePending when the current * transport/application buffers are empty. That is correct for * completed responses, but not for an active streaming response: * the application may need another ResponseEvent call to produce * the next media chunk even though SendData is currently empty. * * Without this re-arm, an H2 video stream can stop after the first * chunk whenever no WINDOW_UPDATE or further inbound frame arrives. */ const bool hasActiveStreams = cureq._h2 && !cureq._h2->activeStreams.empty(); const bool hasPendingResponses = cureq._h2 && !cureq._h2->pendingResponses.empty(); const bool hasQueuedApplicationData = cureq.SendData.pos < cureq.SendData.size(); const bool hasQueuedTransportData = cureq.slots[0].csock && cureq.slots[0].csock->hasPendingWrite(); if (hasActiveStreams || hasPendingResponses || hasQueuedApplicationData || hasQueuedTransportData || !fullyFlushed) { cureq.slots[0].ResponsePending.store( true, std::memory_order_release ); netplus::requestWritablePoll(cureq); } return; } Loading Loading
src/httpd.cpp +46 −6 Changes for src/httpd.cpp: 46 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -924,11 +924,15 @@ void libhttppp::HttpEvent::_resumeH2Streams(HttpRequest &cureq, cureq.h2state().peerStreamWindows.erase(sid); streams.erase(it); } else { // Signal the main connection so the epoll loop // re-arms with EPOLLOUT and calls ResponseEvent, // which will resume this stream without waiting // for the client to send WINDOW_UPDATE. cureq.slots[0].ResponsePending.store(true, std::memory_order_release); // Signal and explicitly re-arm the real H2 connection. // The synthetic per-stream request is not registered in // epoll, therefore setting only ResponsePending is not // sufficient to wake the connection again. cureq.slots[0].ResponsePending.store( true, std::memory_order_release ); netplus::requestWritablePoll(cureq); } break; // Don't busy-loop; wait for next event } Loading Loading @@ -1924,7 +1928,43 @@ void libhttppp::HttpEvent::ResponseEvent(netplus::con &curcon,const int tid,ULON // DATA generated above must be handed to the socket now. If the // socket is temporarily blocked, _flushSendDataNow() re-arms the // writable event so the response cannot remain parked forever. _flushSendDataNow(cureq); const bool fullyFlushed = _flushSendDataNow(cureq); /* * _flushSendDataNow() clears ResponsePending when the current * transport/application buffers are empty. That is correct for * completed responses, but not for an active streaming response: * the application may need another ResponseEvent call to produce * the next media chunk even though SendData is currently empty. * * Without this re-arm, an H2 video stream can stop after the first * chunk whenever no WINDOW_UPDATE or further inbound frame arrives. */ const bool hasActiveStreams = cureq._h2 && !cureq._h2->activeStreams.empty(); const bool hasPendingResponses = cureq._h2 && !cureq._h2->pendingResponses.empty(); const bool hasQueuedApplicationData = cureq.SendData.pos < cureq.SendData.size(); const bool hasQueuedTransportData = cureq.slots[0].csock && cureq.slots[0].csock->hasPendingWrite(); if (hasActiveStreams || hasPendingResponses || hasQueuedApplicationData || hasQueuedTransportData || !fullyFlushed) { cureq.slots[0].ResponsePending.store( true, std::memory_order_release ); netplus::requestWritablePoll(cureq); } return; } Loading