Loading debian/changelog +7 −0 Original line number Diff line number Diff line libhttppp (20260404+2) unstable; urgency=medium * Remove all debug std::cerr logging from Http2RequestEvent/ResponseEvent to eliminate data races on _ZSt4cerr across worker threads -- Jan Koester <jan.koester@tuxist.de> Fri, 04 Apr 2026 00:00:00 +0000 libhttppp (20260404+1) unstable; urgency=medium * Add streaming body callbacks: onH2StreamHeaders, onH3StreamHeaders, Loading src/httpd.cpp +0 −94 Original line number Diff line number Diff line Loading @@ -500,15 +500,10 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, } if (ss->totalSent >= content_length) { std::cerr << "[H2-STREAM] COMPLETE (initial): sent " << ss->totalSent << " / " << content_length << std::endl; cureq.h2state().peerStreamWindows.erase(sid); } else { // Store for resumption on WINDOW_UPDATE cureq.h2state().activeStreams[sid] = ss; std::cerr << "[H2-STREAM] parked sid=" << sid << " sent=" << ss->totalSent << " / " << content_length << std::endl; // Immediately kick off the first data fetch — don't wait // for an external WINDOW_UPDATE. Without this, streaming // responses with empty initial body never send any DATA, Loading Loading @@ -644,8 +639,6 @@ void libhttppp::HttpEvent::_resumeH2Streams(HttpRequest &cureq, } if (ss->totalSent >= ss->contentLength) { std::cerr << "[H2-STREAM] COMPLETE sid=" << sid << " sent=" << ss->totalSent << std::endl; cureq.h2state().peerStreamWindows.erase(sid); streams.erase(it); continue; Loading Loading @@ -709,9 +702,6 @@ void libhttppp::HttpEvent::_resumeH2Streams(HttpRequest &cureq, } if (ss->emptyCount > 500) { // Genuine stall — send END_STREAM std::cerr << "[H2-STREAM] STALLED sid=" << sid << " sent=" << ss->totalSent << " / " << ss->contentLength << std::endl; out += h2BuildFrame(H2_FRAME_DATA, H2_FLAG_END_STREAM, sid, ""); cureq.h2state().peerStreamWindows.erase(sid); streams.erase(it); Loading @@ -726,8 +716,6 @@ void libhttppp::HttpEvent::_resumeH2Streams(HttpRequest &cureq, } if (ss->totalSent >= ss->contentLength) { std::cerr << "[H2-STREAM] COMPLETE sid=" << sid << " sent=" << ss->totalSent << std::endl; cureq.h2state().peerStreamWindows.erase(sid); streams.erase(it); break; Loading Loading @@ -766,7 +754,6 @@ bool libhttppp::HttpEvent::Http2RequestEvent(netplus::con &curcon, cureq.h2state().serverPrefaceSent = true; out += h2BuildSettings(); out += h2ConnectionWindowBoost(); std::cerr << "[H2-PREFACE] Sent SETTINGS + connection window boost, out.size=" << out.size() << std::endl; } // Process all complete frames in RecvData Loading Loading @@ -916,15 +903,6 @@ reprocess: } else { it->second.body.append(data + off, flen); if (flen > 0) { std::cerr << "[H2-RX-DATA] sid=" << sid << " flen=" << flen << " bodyTotal=" << it->second.body.size() << " outSize=" << out.size() << " END_STREAM=" << (endStream ? 1 : 0) << std::endl; } if (endStream) { if (it->second.headersComplete) { off += flen; Loading @@ -940,11 +918,6 @@ reprocess: } } } } else { std::cerr << "[H2-RX-DATA] sid=" << sid << " flen=" << flen << " NOT FOUND in pendingIncoming!" << std::endl; } break; } Loading Loading @@ -1017,33 +990,6 @@ reprocess: done: if (!out.empty()) { // DEBUG: validate H2 frames before writing to SendData { size_t voff = 0; while (voff + H2_FRAME_HEADER_LEN <= out.size()) { uint32_t vlen = (static_cast<uint8_t>(out[voff]) << 16) | (static_cast<uint8_t>(out[voff+1]) << 8) | static_cast<uint8_t>(out[voff+2]); uint8_t vtype = static_cast<uint8_t>(out[voff+3]); if (vlen > 16384 && vtype == H2_FRAME_DATA) { std::cerr << "[H2-VALIDATE] OVERSIZED DATA frame! len=" << vlen << " at offset=" << voff << " out.size=" << out.size() << std::endl; } if (vlen > 16777215) { std::cerr << "[H2-VALIDATE] CORRUPT frame header! len=" << vlen << " type=" << (int)vtype << " at offset=" << voff << " out.size=" << out.size() << std::endl; break; } voff += H2_FRAME_HEADER_LEN + vlen; } if (voff != out.size()) { std::cerr << "[H2-VALIDATE] MISALIGNED frames! consumed=" << voff << " out.size=" << out.size() << std::endl; } } cureq.SendData.append(out.data(), out.size()); } Loading Loading @@ -1376,10 +1322,6 @@ void libhttppp::HttpEvent::Http3StreamEvent(netplus::socket *sock, ++empty_streak; } if (empty_streak >= max_empty) { std::cerr << "[H3-STREAM] STALLED sid=" << stream_id << " sent=" << sent << " / " << content_length << std::endl; break; } // Brief sleep to let upstream produce data. Loading Loading @@ -1583,24 +1525,6 @@ void libhttppp::HttpEvent::ResponseEvent(netplus::con &curcon,const int tid,ULON if (last) break; } if (!batch.empty()) { // DEBUG: validate batch frames { size_t voff = 0; while (voff + H2_FRAME_HEADER_LEN <= batch.size()) { uint32_t vlen = (static_cast<uint8_t>(batch[voff]) << 16) | (static_cast<uint8_t>(batch[voff+1]) << 8) | static_cast<uint8_t>(batch[voff+2]); if (vlen > 16384) { std::cerr << "[H2-VALIDATE-RESP-BATCH] OVERSIZED frame len=" << vlen << " at offset=" << voff << std::endl; } voff += H2_FRAME_HEADER_LEN + vlen; } if (voff != batch.size()) { std::cerr << "[H2-VALIDATE-RESP-BATCH] MISALIGNED! consumed=" << voff << " batch.size=" << batch.size() << std::endl; } } cureq.SendData.append(batch.data(), batch.size()); } if (pending.offset >= pending.body.size()) { Loading @@ -1617,24 +1541,6 @@ void libhttppp::HttpEvent::ResponseEvent(netplus::con &curcon,const int tid,ULON out.reserve(4096); _resumeH2Streams(cureq, out, tid, args); if (!out.empty()) { // DEBUG: validate resume frames { size_t voff = 0; while (voff + H2_FRAME_HEADER_LEN <= out.size()) { uint32_t vlen = (static_cast<uint8_t>(out[voff]) << 16) | (static_cast<uint8_t>(out[voff+1]) << 8) | static_cast<uint8_t>(out[voff+2]); if (vlen > 16384) { std::cerr << "[H2-VALIDATE-RESUME] OVERSIZED frame len=" << vlen << " at offset=" << voff << std::endl; } voff += H2_FRAME_HEADER_LEN + vlen; } if (voff != out.size()) { std::cerr << "[H2-VALIDATE-RESUME] MISALIGNED! consumed=" << voff << " out.size=" << out.size() << std::endl; } } cureq.SendData.append(out.data(), out.size()); } } Loading Loading
debian/changelog +7 −0 Original line number Diff line number Diff line libhttppp (20260404+2) unstable; urgency=medium * Remove all debug std::cerr logging from Http2RequestEvent/ResponseEvent to eliminate data races on _ZSt4cerr across worker threads -- Jan Koester <jan.koester@tuxist.de> Fri, 04 Apr 2026 00:00:00 +0000 libhttppp (20260404+1) unstable; urgency=medium * Add streaming body callbacks: onH2StreamHeaders, onH3StreamHeaders, Loading
src/httpd.cpp +0 −94 Original line number Diff line number Diff line Loading @@ -500,15 +500,10 @@ void libhttppp::HttpEvent::_dispatchH2Stream(HttpRequest &cureq, } if (ss->totalSent >= content_length) { std::cerr << "[H2-STREAM] COMPLETE (initial): sent " << ss->totalSent << " / " << content_length << std::endl; cureq.h2state().peerStreamWindows.erase(sid); } else { // Store for resumption on WINDOW_UPDATE cureq.h2state().activeStreams[sid] = ss; std::cerr << "[H2-STREAM] parked sid=" << sid << " sent=" << ss->totalSent << " / " << content_length << std::endl; // Immediately kick off the first data fetch — don't wait // for an external WINDOW_UPDATE. Without this, streaming // responses with empty initial body never send any DATA, Loading Loading @@ -644,8 +639,6 @@ void libhttppp::HttpEvent::_resumeH2Streams(HttpRequest &cureq, } if (ss->totalSent >= ss->contentLength) { std::cerr << "[H2-STREAM] COMPLETE sid=" << sid << " sent=" << ss->totalSent << std::endl; cureq.h2state().peerStreamWindows.erase(sid); streams.erase(it); continue; Loading Loading @@ -709,9 +702,6 @@ void libhttppp::HttpEvent::_resumeH2Streams(HttpRequest &cureq, } if (ss->emptyCount > 500) { // Genuine stall — send END_STREAM std::cerr << "[H2-STREAM] STALLED sid=" << sid << " sent=" << ss->totalSent << " / " << ss->contentLength << std::endl; out += h2BuildFrame(H2_FRAME_DATA, H2_FLAG_END_STREAM, sid, ""); cureq.h2state().peerStreamWindows.erase(sid); streams.erase(it); Loading @@ -726,8 +716,6 @@ void libhttppp::HttpEvent::_resumeH2Streams(HttpRequest &cureq, } if (ss->totalSent >= ss->contentLength) { std::cerr << "[H2-STREAM] COMPLETE sid=" << sid << " sent=" << ss->totalSent << std::endl; cureq.h2state().peerStreamWindows.erase(sid); streams.erase(it); break; Loading Loading @@ -766,7 +754,6 @@ bool libhttppp::HttpEvent::Http2RequestEvent(netplus::con &curcon, cureq.h2state().serverPrefaceSent = true; out += h2BuildSettings(); out += h2ConnectionWindowBoost(); std::cerr << "[H2-PREFACE] Sent SETTINGS + connection window boost, out.size=" << out.size() << std::endl; } // Process all complete frames in RecvData Loading Loading @@ -916,15 +903,6 @@ reprocess: } else { it->second.body.append(data + off, flen); if (flen > 0) { std::cerr << "[H2-RX-DATA] sid=" << sid << " flen=" << flen << " bodyTotal=" << it->second.body.size() << " outSize=" << out.size() << " END_STREAM=" << (endStream ? 1 : 0) << std::endl; } if (endStream) { if (it->second.headersComplete) { off += flen; Loading @@ -940,11 +918,6 @@ reprocess: } } } } else { std::cerr << "[H2-RX-DATA] sid=" << sid << " flen=" << flen << " NOT FOUND in pendingIncoming!" << std::endl; } break; } Loading Loading @@ -1017,33 +990,6 @@ reprocess: done: if (!out.empty()) { // DEBUG: validate H2 frames before writing to SendData { size_t voff = 0; while (voff + H2_FRAME_HEADER_LEN <= out.size()) { uint32_t vlen = (static_cast<uint8_t>(out[voff]) << 16) | (static_cast<uint8_t>(out[voff+1]) << 8) | static_cast<uint8_t>(out[voff+2]); uint8_t vtype = static_cast<uint8_t>(out[voff+3]); if (vlen > 16384 && vtype == H2_FRAME_DATA) { std::cerr << "[H2-VALIDATE] OVERSIZED DATA frame! len=" << vlen << " at offset=" << voff << " out.size=" << out.size() << std::endl; } if (vlen > 16777215) { std::cerr << "[H2-VALIDATE] CORRUPT frame header! len=" << vlen << " type=" << (int)vtype << " at offset=" << voff << " out.size=" << out.size() << std::endl; break; } voff += H2_FRAME_HEADER_LEN + vlen; } if (voff != out.size()) { std::cerr << "[H2-VALIDATE] MISALIGNED frames! consumed=" << voff << " out.size=" << out.size() << std::endl; } } cureq.SendData.append(out.data(), out.size()); } Loading Loading @@ -1376,10 +1322,6 @@ void libhttppp::HttpEvent::Http3StreamEvent(netplus::socket *sock, ++empty_streak; } if (empty_streak >= max_empty) { std::cerr << "[H3-STREAM] STALLED sid=" << stream_id << " sent=" << sent << " / " << content_length << std::endl; break; } // Brief sleep to let upstream produce data. Loading Loading @@ -1583,24 +1525,6 @@ void libhttppp::HttpEvent::ResponseEvent(netplus::con &curcon,const int tid,ULON if (last) break; } if (!batch.empty()) { // DEBUG: validate batch frames { size_t voff = 0; while (voff + H2_FRAME_HEADER_LEN <= batch.size()) { uint32_t vlen = (static_cast<uint8_t>(batch[voff]) << 16) | (static_cast<uint8_t>(batch[voff+1]) << 8) | static_cast<uint8_t>(batch[voff+2]); if (vlen > 16384) { std::cerr << "[H2-VALIDATE-RESP-BATCH] OVERSIZED frame len=" << vlen << " at offset=" << voff << std::endl; } voff += H2_FRAME_HEADER_LEN + vlen; } if (voff != batch.size()) { std::cerr << "[H2-VALIDATE-RESP-BATCH] MISALIGNED! consumed=" << voff << " batch.size=" << batch.size() << std::endl; } } cureq.SendData.append(batch.data(), batch.size()); } if (pending.offset >= pending.body.size()) { Loading @@ -1617,24 +1541,6 @@ void libhttppp::HttpEvent::ResponseEvent(netplus::con &curcon,const int tid,ULON out.reserve(4096); _resumeH2Streams(cureq, out, tid, args); if (!out.empty()) { // DEBUG: validate resume frames { size_t voff = 0; while (voff + H2_FRAME_HEADER_LEN <= out.size()) { uint32_t vlen = (static_cast<uint8_t>(out[voff]) << 16) | (static_cast<uint8_t>(out[voff+1]) << 8) | static_cast<uint8_t>(out[voff+2]); if (vlen > 16384) { std::cerr << "[H2-VALIDATE-RESUME] OVERSIZED frame len=" << vlen << " at offset=" << voff << std::endl; } voff += H2_FRAME_HEADER_LEN + vlen; } if (voff != out.size()) { std::cerr << "[H2-VALIDATE-RESUME] MISALIGNED! consumed=" << voff << " out.size=" << out.size() << std::endl; } } cureq.SendData.append(out.data(), out.size()); } } Loading