Skip to content

Commit f236cfe

Browse files
vzaidmanfacebook-github-bot
authored andcommitted
fix RCTBundleURLProvider crash when failing to check isPackagerRunning (facebook#55761)
Summary: In certain situations, where there are network issues reaching the Dev Server, the app crashes because of waiting too long on a semaphore. Instead, reduce the timeout on the `/status` request to 6 seconds, which is plenty of time to validate that the Dev Server is running, and reduce the timeout for the semaphore to 8 seconds, in case the request still won't finish by then. Changelog: [iOS][Fixed] not crashing on network issues with connecting to DevServer Reviewed By: cipolleschi Differential Revision: D94382277
1 parent 8475dcc commit f236cfe

File tree

1 file changed

+25
-6
lines changed

1 file changed

+25
-6
lines changed

packages/react-native/React/Base/RCTBundleURLProvider.mm

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ void RCTBundleURLProviderAllowPackagerServerAccess(BOOL allowed)
3131
static NSString *const kRCTEnableDevKey = @"RCT_enableDev";
3232
static NSString *const kRCTEnableMinificationKey = @"RCT_enableMinification";
3333
static NSString *const kRCTInlineSourceMapKey = @"RCT_inlineSourceMap";
34+
static const NSTimeInterval kRCTPackagerStatusRequestTimeout = 6;
35+
static const NSTimeInterval kRCTPackagerStatusRequestTimeoutGraceTime = 2;
3436

3537
@implementation RCTBundleURLProvider
3638

@@ -96,22 +98,39 @@ + (BOOL)isPackagerRunning:(NSString *)hostPort scheme:(NSString *)scheme
9698
NSURLSession *session = [NSURLSession sharedSession];
9799
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
98100
cachePolicy:NSURLRequestUseProtocolCachePolicy
99-
timeoutInterval:10];
101+
timeoutInterval:kRCTPackagerStatusRequestTimeout];
100102
[[RCTDevSupportHttpHeaders sharedInstance] applyHeadersToRequest:request];
101103
__block NSURLResponse *response;
102104
__block NSData *data;
103105

106+
__block BOOL isRunning = NO;
104107
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
105108
[[session dataTaskWithRequest:request
106-
completionHandler:^(NSData *d, NSURLResponse *res, __unused NSError *err) {
109+
completionHandler:^(NSData *d, NSURLResponse *res, NSError *err) {
107110
data = d;
108111
response = res;
112+
NSString *status = [[NSString alloc] initWithData:d encoding:NSUTF8StringEncoding];
113+
isRunning = [status isEqualToString:@"packager-status:running"];
114+
if (!isRunning) {
115+
RCTLogWarn(
116+
@"Packager status check returned unexpected result for %@: %@, error: %@", url, status, err);
117+
}
109118
dispatch_semaphore_signal(semaphore);
110119
}] resume];
111-
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
112-
113-
NSString *status = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
114-
return [status isEqualToString:@"packager-status:running"];
120+
long result = dispatch_semaphore_wait(
121+
semaphore,
122+
dispatch_time(
123+
DISPATCH_TIME_NOW,
124+
(int64_t)((kRCTPackagerStatusRequestTimeout +
125+
// The request timeout does not cover all phases of the request (e.g. DNS resolution),
126+
// so the actual request might take slightly longer than the configured timeout.
127+
kRCTPackagerStatusRequestTimeoutGraceTime) *
128+
NSEC_PER_SEC)));
129+
if (result != 0) {
130+
RCTLogWarn(@"Packager status check timed out for %@", url);
131+
return NO;
132+
}
133+
return isRunning;
115134
}
116135

117136
- (NSString *)guessPackagerHost

0 commit comments

Comments
 (0)