diff --git a/AWSIoT/Internal/AWSIoTMQTTClient.m b/AWSIoT/Internal/AWSIoTMQTTClient.m index 8cce64a6446..2f7b43dfa64 100644 --- a/AWSIoT/Internal/AWSIoTMQTTClient.m +++ b/AWSIoT/Internal/AWSIoTMQTTClient.m @@ -710,10 +710,15 @@ - (void)invalidateReconnectTimer { - (void)cleanUpWebsocketOutputStream { @synchronized(self) { if (self.websocketOutputStream) { - self.websocketOutputStream.delegate = nil; - [self.websocketOutputStream close]; - [self.websocketOutputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - self.websocketOutputStream = nil; + // This `websocketOutputStream` object here is possible to be accessed by other threads + @synchronized(self.websocketOutputStream) { + if (self.websocketOutputStream) { // We'd better double check its existence after obtained the lock + self.websocketOutputStream.delegate = nil; + [self.websocketOutputStream close]; + [self.websocketOutputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + self.websocketOutputStream = nil; + } + } } } } @@ -1262,7 +1267,10 @@ - (void)webSocket:(AWSSRWebSocket *)webSocket didFailWithError:(NSError *)error // Also, the webSocket can be set to nil [self cleanUpWebsocketOutputStream]; - [self.encoderOutputStream close]; + // This `encoderOutputStream` object here is possible to be accessed by other threads + @synchronized (self.encoderOutputStream) { + [self.encoderOutputStream close]; + } [self.webSocket close]; self.webSocket = nil; @@ -1300,7 +1308,10 @@ - (void)webSocket:(AWSSRWebSocket *)webSocket didCloseWithCode:(NSInteger)code r // The WebSocket has closed. The input/output streams can be closed here. [self cleanUpWebsocketOutputStream]; - [self.encoderOutputStream close]; + // This `encoderOutputStream` object here is possible to be accessed by other threads + @synchronized (self.encoderOutputStream) { + [self.encoderOutputStream close]; + } [self.webSocket close]; self.webSocket = nil; diff --git a/AWSIoT/Internal/AWSIoTStreamThread.m b/AWSIoT/Internal/AWSIoTStreamThread.m index 8ad47bcc445..9597761e1cf 100644 --- a/AWSIoT/Internal/AWSIoTStreamThread.m +++ b/AWSIoT/Internal/AWSIoTStreamThread.m @@ -150,25 +150,33 @@ - (void)cleanUp { } // Make sure we handle the streams in a thread-safe way - if (self.outputStream) { - // Remove from runLoop first before closing - if (self.runLoopForStreamsThread) { - [self.outputStream removeFromRunLoop:self.runLoopForStreamsThread - forMode:NSDefaultRunLoopMode]; + @synchronized(self.outputStream) { + if (self.outputStream) { + // Remove from runLoop first before closing + if (self.runLoopForStreamsThread) { + [self.outputStream removeFromRunLoop:self.runLoopForStreamsThread + forMode:NSDefaultRunLoopMode]; + } + self.outputStream.delegate = nil; + [self.outputStream close]; + self.outputStream = nil; } - self.outputStream.delegate = nil; - [self.outputStream close]; - self.outputStream = nil; } - if (self.decoderInputStream) { - [self.decoderInputStream close]; - self.decoderInputStream = nil; + // Make sure we handle the streams in a thread-safe way + @synchronized(self.decoderInputStream) { + if (self.decoderInputStream) { + [self.decoderInputStream close]; + self.decoderInputStream = nil; + } } - if (self.encoderOutputStream) { - [self.encoderOutputStream close]; - self.encoderOutputStream = nil; + // Make sure we handle the streams in a thread-safe way + @synchronized(self.encoderOutputStream) { + if (self.encoderOutputStream) { + [self.encoderOutputStream close]; + self.encoderOutputStream = nil; + } } } else { AWSDDLogVerbose(@"Skipping disconnect for thread: [%@]", (NSThread *)self); diff --git a/AWSIoT/Internal/MQTTSDK/AWSMQTTEncoder.m b/AWSIoT/Internal/MQTTSDK/AWSMQTTEncoder.m index 9a6fc4986e7..9c396c89189 100644 --- a/AWSIoT/Internal/MQTTSDK/AWSMQTTEncoder.m +++ b/AWSIoT/Internal/MQTTSDK/AWSMQTTEncoder.m @@ -44,10 +44,15 @@ - (void)open { } - (void)close { - AWSDDLogDebug(@"closing encoder stream."); - [self.stream close]; - [self.stream setDelegate:nil]; - self.stream = nil; + // Make sure we handle the streams in a thread-safe way + @synchronized (self.stream) { + if (self.stream) { // We'd better double check that the stream is not nil + AWSDDLogDebug(@"closing encoder stream."); + [self.stream close]; + [self.stream setDelegate:nil]; + self.stream = nil; + } + } } //This is executed in the runLoop.