Skip to content

Commit

Permalink
Workaround to open file handles for loaded assets (#1287)
Browse files Browse the repository at this point in the history
We ran into an issue that our production app was crashing on certain devices as we opened too many file descriptors (> 256). See some details here: https://wilsonmar.github.io/maximum-limits/

We found that macOS will keep image files handles open for `NSImage` lifetime in some cases:
```
  // this will keep file open only if image is loaded from app bundle
  NSString *path = [[NSBundle mainBundle] pathForResource:@"slider" ofType:@"png" inDirectory:@"assets"];
  _image = [[NSImage alloc] initWithContentsOfFile:path];

  // this will not keep file open
  _image = [[NSImage alloc] initWithContentsOfFile:@"/Users/theUser/Downloads/slider.png"];

  // this will not keep file open
  NSData *data = [NSData dataWithContentsOfFile:path];
  _image = [[NSImage alloc] initWithData:data];
```
This can be documented behavior, but I didn't find any reference in documentation or headers.

Test Plan:
- build and run prod version of app
- explore open files for Messenger process in Activity Monitor
- confirm no assets are open

Co-authored-by: Scott Kyle <skyle@fb.com>
  • Loading branch information
christophpurrer and appden authored Sep 22, 2022
1 parent d8612d0 commit bb8a035
Showing 1 changed file with 6 additions and 3 deletions.
9 changes: 6 additions & 3 deletions React/Base/RCTUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -905,9 +905,12 @@ BOOL RCTIsLocalAssetURL(NSURL *__nullable imageURL)
}
#if !TARGET_OS_OSX // TODO(macOS GH#774)
image = [UIImage imageWithContentsOfFile:filePath];
#else // TODO(macOS GH#774)
image = [[NSImage alloc] initWithContentsOfFile:filePath]; // TODO(macOS GH#774)
#endif // TODO(macOS GH#774)
#else // [TODO(macOS GH#774)
// macOS keeps file handles in open state for lifetime of image if "initWithContentsOfFile:" is used with path inside app bundle
// Workaround is to load file in data and then convert data to image
NSData *data = [NSData dataWithContentsOfFile:filePath];
image = [[NSImage alloc] initWithData:data];
#endif // ]TODO(macOS GH#774)
}
}

Expand Down

0 comments on commit bb8a035

Please sign in to comment.