Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix support for blobs larger than 64 KB on Android #31789
Fix support for blobs larger than 64 KB on Android #31789
Changes from 7 commits
1b92132
2116f50
2ffbd5a
57e3173
005d4a6
82d3284
4b886e2
58c8354
f8d3b85
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One pretty valid concern raised by @ShikaSD is that creating a new thread for each URI is a good idea can consume quite a bit of memory by accident.
What do you think about going ahead with your suggestion about conditionally creating he thread when the blob is bigger than the pipe?
Additionally, @ShikaSD suggested using an executor here to schedule things on a single thread.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to determine the pipe capacity using
Os.fcntlInt
, but this method is only available from API 30 (see the documentation).Probably we could call
fcntl(2)
from native code instead. Another way to determine the pipe capacity would be to open and read/proc/sys/fs/pipe-max-size
. Hopefully it's enough to assign 65536 directly for now.I've also updated the example in RNTester so now it includes two images – one smaller and one larger than 64 KB.
Just to be safe, I've also checked if it works properly for an image exactly of size equal to pipe capacity. In order to generate images of arbitrary size, I've implemented a HTTP server in Flask which appends null bytes to an existing JPG image and returns the modified image in the response:
In RNTester app I've replaced the URLs:
Using the new implementation with conditional write, all images are loaded properly, so it should be safe to use the condition
data.length <= PIPE_CAPACITY
.Good idea! Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens in this situation? Should we somehow close or notify with failure?
Previously, the parent method would return
null
instead ofreadSide
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the new implementation returns a
ParcelFileDescriptor
immediately, i.e. before callingwrite
(which possibly could fail later on), we cannot returnnull
as previously.AutoCloseOutputStream
ensures that the write side descriptor always gets closed, no matter if the write was successful or not. In case of an I/O error, the write side descriptor gets closed, and reading from a broken pipe will also result in anIOException
on the reader side.According to Android documentation, the reader is responsible for closing the read side descriptor:
So it should be safe to return
ParcelFileDescriptor
instead ofnull
, since the reader is responsible for closing it.The opposite case is when the reader closes the read side descriptor on purpose, for example when unmounting an image component before it was fully loaded (i.e. partial read). In such case, the write call fails and the write side descriptor gets closed as well, so there is no resource leak.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing! Thank you for the detailed explanation.