Loading src/connection.h +16 −0 Original line number Diff line number Diff line Loading @@ -190,6 +190,22 @@ namespace netplus { condata<char> RecvData; condata<char> SendData; // True if any slot has offloaded work in flight (see ConSlot::PendingOps) -- // the idle reaper (event/epoll.cpp, event/kqueue.cpp) checks this before closing // a connection purely by lasteventime age. lasteventime is only refreshed by the // synchronous IoEventHandler read/write path; a background dispatch task (e.g. // libhttppp's H2 offload pool writing a slow stream's response) doesn't touch it, // so without this check a connection that's otherwise quiet while one such task // is still running looks idle and gets closed out from under it -- producing a // local FIN while the peer is still legitimately waiting on the response, which // the peer never answers with its own FIN (FIN_WAIT_2 buildup under load). bool hasPendingOps() const { for (auto &s : slots) { if (s.PendingOps.load(std::memory_order_relaxed) > 0) return true; } return false; } int DebugId=0; // Application-defined extension data. Loading src/event/epoll.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -639,6 +639,7 @@ namespace netplus { for (auto& kv : CONNECTIONS) { if (kv.second->ownerPollFd != _pollFD) continue; // not ours to close if (now - kv.second->lasteventime < idleTimeoutSeconds) continue; if (kv.second->hasPendingOps()) continue; // background dispatch task still using this connection idleFds.push_back(kv.first); } } Loading src/event/kqueue.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -750,6 +750,7 @@ namespace netplus { for (auto& kv : CONNECTIONS) { if (kv.second->ownerPollFd != _kqfd) continue; // not ours to close if (now - kv.second->lasteventime < idleTimeoutSeconds) continue; if (kv.second->hasPendingOps()) continue; // background dispatch task still using this connection idleFds.push_back(kv.first); } } Loading Loading
src/connection.h +16 −0 Original line number Diff line number Diff line Loading @@ -190,6 +190,22 @@ namespace netplus { condata<char> RecvData; condata<char> SendData; // True if any slot has offloaded work in flight (see ConSlot::PendingOps) -- // the idle reaper (event/epoll.cpp, event/kqueue.cpp) checks this before closing // a connection purely by lasteventime age. lasteventime is only refreshed by the // synchronous IoEventHandler read/write path; a background dispatch task (e.g. // libhttppp's H2 offload pool writing a slow stream's response) doesn't touch it, // so without this check a connection that's otherwise quiet while one such task // is still running looks idle and gets closed out from under it -- producing a // local FIN while the peer is still legitimately waiting on the response, which // the peer never answers with its own FIN (FIN_WAIT_2 buildup under load). bool hasPendingOps() const { for (auto &s : slots) { if (s.PendingOps.load(std::memory_order_relaxed) > 0) return true; } return false; } int DebugId=0; // Application-defined extension data. Loading
src/event/epoll.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -639,6 +639,7 @@ namespace netplus { for (auto& kv : CONNECTIONS) { if (kv.second->ownerPollFd != _pollFD) continue; // not ours to close if (now - kv.second->lasteventime < idleTimeoutSeconds) continue; if (kv.second->hasPendingOps()) continue; // background dispatch task still using this connection idleFds.push_back(kv.first); } } Loading
src/event/kqueue.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -750,6 +750,7 @@ namespace netplus { for (auto& kv : CONNECTIONS) { if (kv.second->ownerPollFd != _kqfd) continue; // not ours to close if (now - kv.second->lasteventime < idleTimeoutSeconds) continue; if (kv.second->hasPendingOps()) continue; // background dispatch task still using this connection idleFds.push_back(kv.first); } } Loading