From 0d4b0e941725657d8e63940428888aaceff505ad Mon Sep 17 00:00:00 2001 From: Lukas Weber Date: Tue, 11 Feb 2020 10:52:45 -0800 Subject: [PATCH] Fixes RCTReconnectingWebSocket connecting in infinite loop when stopped before it connects (#26864) Summary: When `[RCTReconnectingWebSocket stop]` is called and `[RCTReconnectingWebSocket reconnect]` is scheduled afterwards (i.e. connection didn't happen before `[RCTReconnectingWebSocket stop]` being invoked), it will keep reconnecting forever. Also fixes retain loop in block within `[RCTReconnectingWebSocket reconnect]`. When RCTReconnectingWebSocket is stopped and reference to it set to nil, block in reconnect will still keep self alive and reconnecting forever. I found this edge case when I tried to stop RCTPackagerConnection after some time, so it doesn't spam with `[] nw_socket_handle_socket_event [C34585.1:1] Socket SO_ERROR [61: Connection refused]` when we don' have Metro running (we have brownfield app, so iOS devs don't need Metro running most of the time). ## Changelog [iOS] [Fixed] - RCTReconnectingWebSocket is reconnecting infinitely when stopped before getting connected Pull Request resolved: https://github.com/facebook/react-native/pull/26864 Test Plan: - Put breakpoint into `[RCTReconnectingWebSocket reconnect]` - Start sample RN app **without having Metro running** - Into AppDelegate add something like ```objc dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [RCTPackagerConnection.sharedPackagerConnection stop] }); ``` - After the previous block is dispatched reconnect should not be invoked anymore Reviewed By: motiz88 Differential Revision: D19767742 Pulled By: rickhanlonii fbshipit-source-id: dabb2369b06217b961e9d2611257c106d350f70c --- Libraries/WebSocket/RCTReconnectingWebSocket.m | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Libraries/WebSocket/RCTReconnectingWebSocket.m b/Libraries/WebSocket/RCTReconnectingWebSocket.m index 6c6401ee91f6d2..cd85e9b81ea654 100644 --- a/Libraries/WebSocket/RCTReconnectingWebSocket.m +++ b/Libraries/WebSocket/RCTReconnectingWebSocket.m @@ -20,6 +20,7 @@ @interface RCTReconnectingWebSocket () @implementation RCTReconnectingWebSocket { NSURL *_url; RCTSRWebSocket *_socket; + BOOL _stopped; } - (instancetype)initWithURL:(NSURL *)url queue:(dispatch_queue_t)queue @@ -44,6 +45,7 @@ - (void)send:(id)data - (void)start { [self stop]; + _stopped = NO; _socket = [[RCTSRWebSocket alloc] initWithURL:_url]; _socket.delegate = self; [_socket setDelegateDispatchQueue:_delegateDispatchQueue]; @@ -52,6 +54,7 @@ - (void)start - (void)stop { + _stopped = YES; _socket.delegate = nil; [_socket closeWithCode:1000 reason:@"Invalidated"]; _socket = nil; @@ -64,11 +67,17 @@ - (void)webSocket:(RCTSRWebSocket *)webSocket didReceiveMessage:(id)message - (void)reconnect { + if (_stopped) { + return; + } + __weak RCTSRWebSocket *socket = _socket; + __weak __typeof(self) weakSelf = self; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [self start]; + [weakSelf start]; if (!socket) { - [self reconnect]; + [weakSelf reconnect]; } }); }