Repository navigation
Guard last_event_id() against the async event loop in SSEClient - #2644
Merged
Merged
Conversation
SSEClient::last_event_id() returned a reference to last_event_id_ with no lock, while run_event_loop() assigns it from each event that carries an id. Under start_async() the loop runs on its own thread, so reading the id from the application's thread raced the writes the server drives. The id is now stored and read under a mutex, and last_event_id() returns a copy.
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.
Unsynchronised read of last_event_id() in SSEClient
run_event_loop()assignslast_event_id_from every event with anid:field, and understart_async()that loop runs on its own thread.last_event_id()handed back a reference to the same string without a lock, so an application reading it from its own thread (the README lists it next to the atomicis_connected()) races writes the server controls. I've guarded the member with a mutex and made the getter return a copy.Reviewer notes
std::string::_M_assignin the event loop vs. the caller's copy). The newSSEIntegrationTest.LastEventIdWhileRunningfails under-fsanitize=threadbefore the change and passes after; the SSE tests also pass under the usual ASan build.const std::string &tostd::string.std::string id = sse.last_event_id();and stream insertion still compile unchanged, and I've updated the README snippet, but this may be worth flagging as a small API change.