+34
−22
+8
−0
test/close_race_test.cpp
0 → 100644
+132
−0
Loading
IoEventHandler looked the connection up by fd and then waited for its
event_mutex. If another worker closed it meanwhile (idle reaper, a close
from a re-armed event via requestWritablePoll), the waiting worker still
saw a non-null csock and went on: recv() on the closed fd ("tcp::recvData
failed: Bad file descriptor"), callbacks on a disconnected con, and its
own error path then called CloseEventHandler(fd) -- which, once the
kernel had reused the fd number, closed an unrelated new connection.
The reaper had the same problem: it collected fd numbers and closed by
number later.
- IoEventHandler: after taking event_mutex, go on only if c is still the
connection registered under fd.
- closeConnection(c, fd): takes event_mutex first, then erases and
EPOLL_CTL_DELs only if the map still holds c (lock order
event_mutex -> POLL_HANDLER_MUTEX, as in detachConnection).
- reapIdleConnections: keeps the con, skips it if a worker holds its
event_mutex (busy, not idle) and re-checks idleness under the lock.
New close_race_test: callbacks after DisconnectEvent in 16 of 20 rounds
before, 0 after.
Co-Authored-By:
Claude Opus 5.5 <noreply@anthropic.com>