react-native icon indicating copy to clipboard operation
react-native copied to clipboard

Prevent native blob resource from being de-allocated prematurely

Open awinograd opened this issue 3 years ago • 3 comments

Summary

This PR prevents blob data from being prematurely de-allocated in native code when using slice to create views into an existing blob. Currently, whenever a new blob is created via createFromOptions, BlobManager.js creates a new blobCollector object since options.__collector is never provided.

https://github.com/facebook/react-native/blob/dc80b2dcb52fadec6a573a9dd1824393f8c29fdc/Libraries/Blob/BlobManager.js#L115-L123

When the reference to a blobCollector is garbage collected, the corresponding native memory for the blob data is de-allocated.

https://github.com/facebook/react-native/blob/27651720b40cab564a0cbd41be56a02584e0c73a/Libraries/Blob/RCTBlobCollector.mm#L19-L25

Since, blob.slice() is supposed to create a new view onto the same binary data as the original blob, we need to re-use the same collector object when slicing so that it is not GC'd until the last reference to the binary data is no longer reachable. Currently, since each blob slice gets a new blobCollector object, the memory is de-allocated when the first blob is GC'd.

Fixes https://github.com/facebook/react-native/issues/29970 Fixes https://github.com/facebook/react-native/issues/27857

Changelog

[iOS] [Fixed] - Blob data is no longer prematurely deallocated when using blob.slice

Test Plan

I could use help coming up with a test plan here. I could add a referential equality check for the blob.data.__collector in Blob-test but it doesn't seem quite right to be testing the implementation detail there.

awinograd avatar Apr 20 '21 16:04 awinograd

Platform Engine Arch Size (bytes) Diff
android hermes arm64-v8a 7,104,346 +41
android hermes armeabi-v7a 6,473,107 +40
android hermes x86 7,522,621 +40
android hermes x86_64 7,381,045 +37
android jsc arm64-v8a 8,971,785 +7
android jsc armeabi-v7a 7,703,213 +5
android jsc x86 9,034,393 +6
android jsc x86_64 9,511,776 -3

Base commit: e509007f5714301ebcbb2adf249cafcf7d466606 Branch: main

analysis-bot avatar Apr 20 '21 17:04 analysis-bot

Platform Engine Arch Size (bytes) Diff
ios - universal n/a --

Base commit: 322a796cba3a7fa624ab52803afbe2f29cf3cdc9 Branch: main

analysis-bot avatar Apr 20 '21 17:04 analysis-bot

Hi there, we have been facing this issue for quite a while. We are using a resumable/chunked upload client called tus which uses Blob#slice() under the hood (see tus/tus-js-client#326 for a detailed bug report).

We have been applying this patch (using patch-package) for several months now, and we can confirm that it works. Also a bit unclear how you would test something like this other than saying it has massively reduced our crash rate :)

Without the patch we consistently see crashes with a *** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0] exception.

One of my team members implemented a repro here if anyone is interested: https://github.com/samal-rasmussen/tus-js-client-slice-bug/commit/112843bf46305dd4acf30e059838c9e6fcf9f915

lachenmayer avatar Aug 23 '22 19:08 lachenmayer

@kelset sorry to bother you with a ping, but would be great to get some 👁️ on this PR. Is there anything I can do to entice a maintainer to take a look?

awinograd avatar Dec 02 '22 23:12 awinograd

@cortinico has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

facebook-github-bot avatar Dec 05 '22 11:12 facebook-github-bot

PR build artifact for d064dfe8df29c36d88834f58f995c36456427139 is ready. To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

pull-bot avatar Dec 05 '22 12:12 pull-bot

PR build artifact for d064dfe8df29c36d88834f58f995c36456427139 is ready. To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

pull-bot avatar Dec 05 '22 12:12 pull-bot

This pull request was successfully merged by @awinograd in 36cc71ab36aac5e5a78f2fbae44583d1df9c3cef.

When will my fix make it into a release? | Upcoming Releases

github-actions[bot] avatar Dec 05 '22 15:12 github-actions[bot]

Thank you @kelset @cortinico for pushing this PR forward and getting it merged. Much appreciated!

awinograd avatar Dec 05 '22 15:12 awinograd