UDP control sender can deadlock on exception while holding sendLocker
Summary¶
CClientUDPSocket::SendControlData manually locks sendLocker, removes packet
ownership from the queue, allocates a raw send buffer, copies packet data, and
performs socket sends before manually unlocking. An allocation failure, MFC
exception, or unexpected exception in that region can leave sendLocker held
and leak the removed packet.
This blocks Beta 0.7.3 because the function is explicitly called from another thread and can silently freeze UDP control traffic.
Evidence¶
srchybrid/ClientUDPSocket.cpp:442notes the function runs from a different thread.srchybrid/ClientUDPSocket.cpp:446manually lockssendLocker.srchybrid/ClientUDPSocket.cpp:450removesUDPPackownership from the queue.srchybrid/ClientUDPSocket.cpp:459allocates a rawucharbuffer while the lock is held.srchybrid/ClientUDPSocket.cpp:487manually unlocks after the send loop.
Execution Plan¶
- Revalidate the queue ownership contract and which thread(s) can call
SendControlData. - Replace manual lock/unlock with an exception-safe scoped lock compatible with the existing MFC synchronization style.
- Make removed
UDPPackand temporary send buffer ownership exception-safe without changing packet ordering or resend semantics. - Preserve existing UDP throttler behavior, including requeue-on-send-failure.
- Add targeted coverage for allocation failure or an injected send failure while ensuring the lock is released and the queue remains usable.
- Run Kad/client UDP regression coverage, including the existing crypt-gating seam.
Acceptance Criteria¶
- No exception path can leave
sendLockerlocked. - Removed packets are either sent, requeued, or destroyed exactly once.
- Valid ED2K and Kad UDP send behavior is unchanged.
- The upload bandwidth throttler can continue after injected failure.
Validation¶
- 2026-05-08: Done in app commit
4796d2f. python -m emule_workspace build app --workspace-root . --config Release --platform x64 --variant mainpassed; log rootworkspaces\v0.72a\state\build-logs\20260508-094757.python -m emule_workspace validate --workspace-root .passed.python -m emule_workspace build tests --workspace-root . --config Release --platform x64 --test-run-variant mainpassed; log rootworkspaces\v0.72a\state\build-logs\20260508-094821.- Focused doctest passed:
repos\emulebb-build-tests\build\eMulebb-workspace-v0.72a-eMule-main\x64\Release\emule-tests.exe --test-suite=parity --test-case="Client UDP seam gates outgoing encryption on the global crypt preference". - Code validation:
SendControlDatanow uses scoped locking and scoped packet and send-buffer ownership, so exceptions releasesendLockerand do not leak removed packets.