Open Bug 1896447 Opened 27 days ago Updated 24 days ago

Crash in [@ mozilla::ipc::PortLink::SendMessage | IPC_Message_Name=PContent::Msg_GetFilesResponse]

Categories

(Core :: DOM: File, defect)

defect

Tracking

()

People

(Reporter: gsvelto, Unassigned)

Details

(Keywords: crash, Whiteboard: [necko-triaged][necko-priority-new])

Crash Data

Crash report: https://crash-stats.mozilla.org/report/index/33e956a4-39cc-4fee-87f0-918430240512

MOZ_CRASH Reason: MOZ_CRASH(IPC message size is too large)

Top 10 frames:

0  libxul.so  mozilla::ipc::PortLink::SendMessage(mozilla::UniquePtr<IPC::Message, mozilla:...  ipc/glue/MessageLink.cpp:105
0  libxul.so  mozilla::ipc::MessageChannel::SendMessageToLink(mozilla::UniquePtr<IPC::Messa...  ipc/glue/MessageChannel.cpp:811
0  libxul.so  mozilla::ipc::MessageChannel::Send(mozilla::UniquePtr<IPC::Message, mozilla::...  ipc/glue/MessageChannel.cpp:780
1  libxul.so  mozilla::ipc::IProtocol::ChannelSend(mozilla::UniquePtr<IPC::Message, mozilla...  ipc/glue/ProtocolUtils.cpp:520
2  libxul.so  mozilla::dom::PContentParent::SendGetFilesResponse(nsID const&, mozilla::dom:...  ipc/ipdl/PContentParent.cpp:4035
3  libxul.so  mozilla::dom::GetFilesHelperParentCallback::Callback(nsresult, FallibleTArray...  dom/filesystem/GetFilesHelper.cpp:463
4  libxul.so  mozilla::dom::GetFilesHelper::RunCallback(mozilla::dom::GetFilesCallback*)  dom/filesystem/GetFilesHelper.cpp:377
4  libxul.so  mozilla::dom::GetFilesHelper::OperationCompleted()  dom/filesystem/GetFilesHelper.cpp:231
5  libxul.so  mozilla::dom::GetFilesHelper::Run()  dom/filesystem/GetFilesHelper.cpp:212
6  libxul.so  mozilla::RunnableTask::Run()  xpcom/threads/TaskController.cpp:580

Comments in the crashes point to users trying to upload large files or entire directories to Google Drive / OneDrive:

upload big file to google drive

uploaded a big folder to google drive

Uploading a directory of files

This crash happens frequently when uploading to OneDrive. Please fix, tks!!

Want to upload a Huge Folder with 100k files. Getting crashed.

mega lame, twice I've tried an upload to a trusted site and it crashes.

Trying to upload a folder (fairly big) to Google Drive

Nika - I'm guessing the 'right' solution is to have some type of chunker to let us limit the size of a single IPC here. There aren't any generic tools for splitting IPCs up or useful code patterns to do this, are there?

Severity: -- → S3
Flags: needinfo?(nika)
Priority: -- → P3
Whiteboard: [necko-triaged][necko-priority-new]
Component: Networking: File → DOM: File

Pulling severity/priority so DOM can triage

Severity: S3 → --
Priority: P3 → --

The situation here appears to be specifically that we're sending a large number of files over IPC. We handle individual large files with BlobImpl moving them async using a RemoteLazyStream, but the file list itself is still sent inline. Based on the comments, I would guess that in a case where someone selects 100k files, we end up blowing out the maximum message size, due to needing to send the file handles and metadata for 100k distinct files and streams.

While we've done some work to make sending large amounts of simple data easier, we don't have any workarounds for sending massive amounts of complex IPC data within a single message. If sent, this message with 100k files probably contains 100k Endpoints, but we're falling over here before we even try to serialize these Endpoints into the message fully, meaning we've burned through 256Mb using only the IPCBlob metadata overhead like file paths.

To me the "obvious" thing to do here would be to make RecvGetFilesRequest construct a new managed actor like PGetFilesRequest, which has an async AddFile(IPCBlob aFile) message called by the parent to send a file to content for each file selected, then an async __delete__(nsresult aStatus) of some kind when complete. I think the actor would replace the need for manual UUID tracking to correlate the request & response with one-another, and would allow sending the response in multiple messages. There is some additional message overhead for sending every file in its own message, so if that ends up being a problem I suppose it could also be batched into smaller groups of files.

I tried to guess at where chromium is handling similar things, and I think their equivalent message is marked as [UnlimitedSize] to bypass their message size restriction (though there is a comment suggesting they'd like to make it use chunked messages instead: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/choosers/file_chooser.mojom;l=108-109;drc=047c7dc4ee1ce908d7fea38ca063fa2f80f92c77).

As an additional note, as far as I can tell this code is only used by specifically <input type="file" webkitdirectory> elements. It seems like the fetching happens after the file picker API has already picked files, but before we notify listeners of the input change, so perhaps there is some other optimization which we can/should be doing there to avoid this extra IPC completely and the entire extra request and async round-trip.

Flags: needinfo?(nika)
Severity: -- → S3
You need to log in before you can comment on or make changes to this bug.