Skip to content

Commit e86e61b

Browse files
committed
IXWebSocketTransport::setReadyState(): Run under lock
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.
1 parent 8115594 commit e86e61b

File tree

2 files changed

+8
-0
lines changed

2 files changed

+8
-0
lines changed

ixwebsocket/IXWebSocketTransport.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,12 @@ namespace ix
205205

206206
void WebSocketTransport::setReadyState(ReadyState readyState)
207207
{
208+
// Lock the _setReadyStateMutex for the duration of this
209+
// method. This ensures that only a single thread runs the
210+
// logic below avoiding concurrent execution of the
211+
// close callback my multiple threads at the same time.
212+
std::lock_guard<std::mutex> lock(_setReadyStateMutex);
213+
208214
// No state change, return
209215
if (_readyState == readyState) return;
210216

ixwebsocket/IXWebSocketTransport.h

+2
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ namespace ix
185185

186186
// Hold the state of the connection (OPEN, CLOSED, etc...)
187187
std::atomic<ReadyState> _readyState;
188+
// Mutex to serialize setReadyState() execution.
189+
std::mutex _setReadyStateMutex;
188190

189191
OnCloseCallback _onCloseCallback;
190192
std::string _closeReason;

0 commit comments

Comments
 (0)