core: event: prevent libevent timer socket deadlock - #445
Open
zshuang0316 wants to merge 1 commit into
Open
Conversation
The libevent timer callback writes notifications from the event-loop thread. If its socket buffer fills, a blocking send waits for the same loop to drain the read side and deadlocks the loop. Make the write endpoint nonblocking and treat a would-block result as an already pending timer notification. Read errors from the write socket instead of the timer callback descriptor. Signed-off-by: zshuang0316 <zshuang0316@163.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The libevent timeout callback writes timer notifications from the event-loop
thread. If unread notifications fill the socket buffer, the blocking
send()waits for that same event loop to drain the read endpoint and theloop deadlocks.
Make the timer write endpoint nonblocking and treat
EAGAIN/EWOULDBLOCKas an already-pending notification. Also retrieve send errorsfrom the actual write endpoint instead of the libevent timer callback fd,
which is
-1.The issue was observed in Fluent Bit on Windows. A Windows Performance
Recorder trace showed the engine thread blocked through:
cb_timeout() -> send() -> WSPSend() -> SockWaitForSingleObject()The same issue can affect any platform explicitly using Monkey's libevent
backend.
Related downstream PR: fluent/fluent-bit#12241
Testing
Built Monkey with the libevent backend on Windows and ran:
mk-test-event_timeout.exeResult:
SUCCESS: All unit tests have passed.