Skip to content

Commit 156a9a2

Browse files
generatedunixname1608173377072046meta-codesync[bot]
authored andcommitted
Include errno in iOS bundle open/stat failure messages (#58383)
Summary: Pull Request resolved: #58383 When `RCTJavaScriptLoader` fails to open or stat the JS bundle, the resulting `NSError` carried only the bundle path. The `errno` set by the failing `fopen()` / `stat()` was discarded, so a bundle that is absent (`ENOENT`) was indistinguishable from one that exists but cannot be read (`EACCES`, `EIO`). Because `RCTInstance handleBundleLoadingError:` turns every loader error into a fatal, this is the only diagnostic information available after the fact — and there was none. Capture `errno` immediately after the failing call (before any intervening call can clobber it) and surface it in two ways: appended to the localized description as `(errno <n>: <strerror>)`, which is what ends up in the crash report, and as an `NSPOSIXErrorDomain` error under `NSUnderlyingErrorKey` for programmatic consumers. Purely additive to error paths that already abort; no behavior change on success. Changelog: [iOS][Changed] - Include `errno` and its description in `RCTJavaScriptLoader` bundle open/stat errors Reviewed By: javache Differential Revision: D118952499 fbshipit-source-id: 6f711dde3969f9fdcd1af300121d954a2da8816e
1 parent 9a49fc2 commit 156a9a2

1 file changed

Lines changed: 17 additions & 2 deletions

File tree

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#import "RCTJavaScriptLoader.h"
99

10+
#import <errno.h>
11+
#import <string.h>
1012
#import <sys/stat.h>
1113

1214
#import <cxxreact/JSBundleType.h>
@@ -138,12 +140,20 @@ + (NSData *)attemptSynchronousLoadOfBundleAtURL:(NSURL *)scriptURL
138140
// modules into JSC as they're required.
139141
FILE *bundle = fopen(scriptURL.path.UTF8String, "r");
140142
if (!bundle) {
143+
// Read errno before anything else can clobber it. Without it a missing bundle (ENOENT) is
144+
// indistinguishable from one that exists but cannot be read (EACCES, EIO), which is the
145+
// difference between a packaging bug and a transient filesystem failure.
146+
const int openErrno = errno;
141147
if (error) {
142148
*error = [NSError
143149
errorWithDomain:RCTJavaScriptLoaderErrorDomain
144150
code:RCTJavaScriptLoaderErrorFailedOpeningFile
145151
userInfo:@{
146-
NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Error opening bundle %@", scriptURL.path]
152+
NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Error opening bundle %@ (errno %d: %s)",
153+
scriptURL.path,
154+
openErrno,
155+
strerror(openErrno)],
156+
NSUnderlyingErrorKey : [NSError errorWithDomain:NSPOSIXErrorDomain code:openErrno userInfo:nil]
147157
}];
148158
}
149159
return nil;
@@ -190,12 +200,17 @@ + (NSData *)attemptSynchronousLoadOfBundleAtURL:(NSURL *)scriptURL
190200

191201
struct stat statInfo;
192202
if (stat(scriptURL.path.UTF8String, &statInfo) != 0) {
203+
const int statErrno = errno;
193204
if (error) {
194205
*error = [NSError
195206
errorWithDomain:RCTJavaScriptLoaderErrorDomain
196207
code:RCTJavaScriptLoaderErrorFailedStatingFile
197208
userInfo:@{
198-
NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Error stating bundle %@", scriptURL.path]
209+
NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Error stating bundle %@ (errno %d: %s)",
210+
scriptURL.path,
211+
statErrno,
212+
strerror(statErrno)],
213+
NSUnderlyingErrorKey : [NSError errorWithDomain:NSPOSIXErrorDomain code:statErrno userInfo:nil]
199214
}];
200215
}
201216
return nil;

0 commit comments

Comments
 (0)