-
Notifications
You must be signed in to change notification settings - Fork 187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IXWebSocketTransport::setReadyState(): Run under lock #540
base: master
Are you sure you want to change the base?
IXWebSocketTransport::setReadyState(): Run under lock #540
Conversation
Can you make the getReadyState use the mutex as well, and stop using an atomic ? Having a mutex AND an atomic seems weird. |
80e6c4f
to
81682fe
Compare
Thanks for the feedback. Done and re-pushed. |
The change looks simple, but all the thread sanitizer checks are not red .... |
Do you have access to a mac machine ? |
|
It's failing on Linux, too. Sorry, it's due to unprotected
Looking at the new diff, going back might be an option IMO and not all that weird: The mutex prevents concurrent execution of |
Alright then ... let's go back to your original idea, but do you mind adding a small comment explaining why we're doing things that way ? |
When setReadyState(CLOSED) is executed from two different threads (the server's thread, detecting a close trying to receive and a separate sending thread), there is a race where both see _readyState as non-CLOSED and both execute the _onCloseCallback(). Worse, the server's thread might be returning from ->run(), unsetting the callback while the other thread is still about to call the _onCloseCallback(), resulting in a crash rather than "just" a duplicate invocation of the callback. This change ensures that setReadyState() *and* the_onCloseCallback() are executed by a single thread till completion, by introducing a new _setReadyStateMutex instance held during setReadyState() execution.
ba0b2dc
to
e86e61b
Compare
Done. Feel free to word-smith during/after the merge. |
When setReadyState(CLOSED) is executed from two different threads (the server's thread, detecting a close trying to receive and a separate sending thread), there is a race where both see _readyState as non-CLOSED and both execute the _onCloseCallback(). Worse, the server's thread might be returning from ->run(), unsetting the callback, while the other thread is still about to call the _onCloseCallback(), resulting in a crash rather than "just" a duplicate invocation.
This change ensures that setReadyState() and the_onCloseCallback() are executed by a single thread till completion.
I was tempted to remove the std::atomic<> for _readyState, but left it assuming it's still good having for getReadyState().
I've first tried _readyState.exchange() which seemed promising, but still crashed once in a while as racing threads do not wait for the _onCloseCallback() to complete.
Closes #539