Patch seems simple but the root cause is complicated, I try to describe it as brief as possible. --- When building ClonedMessageData of a Blob, gecko will clone the inputStream [1] and wrap it as a RemoteLazyStream in serialize phase. If the inputStream is not cloneable (i.e. FileStream), NS_CloneInputStream [2] creates a new pipe and return two cloned stream (reader and writer). Then first, clone reader stream, wrap this cloned inputStream as RemoteLazyStream, serialize it with IPC. Second, copy the source data to writer stream. To start the copy phase, copier holds references of writer stream (this adds two extra refcnt of pipe). And process data copy iff there is read request from child side. Then close the writer stream and release them when done with copy. When child has done with RemoteLazyStream, RemoteLazyInputStreamParent will try to release the cloned inputStream, closing itself explicitly [3]. Logic in nsPipe::OnInputStreamException [3] shows that gecko only shutdown the entire pipe iff there is one stream left and it is the given stream. So here we will not shutdown the pipe because there are two inputStreams left, one is the original inputStream, the other is the cloned inputStream. The cloned inputStream will be closed by ActorDestroy of RemoteLazyInputStreamParent and decrease one refcnt of this pipe. In nsPipe::Release [4], shows that gecko only release the original inputStream iff the refcnt of pipe decrease to one. In the scenario where no read request from child, copier never finishes, two extra refcnt of pipe hold by copier, original inputStream will not be release. Thus, this is why I try to close the inputStream (a.k.a. the original inputStream) in advance when destructing StreamBlobImpl. [1] https://searchfox.org/mozilla-central/source/dom/file/StreamBlobImpl.cpp#73 [2] https://searchfox.org/mozilla-central/source/xpcom/io/nsStreamUtils.cpp#859 [3] https://searchfox.org/mozilla-central/source/xpcom/io/nsPipe3.cpp#905-910 [4] https://searchfox.org/mozilla-central/source/xpcom/io/nsPipe3.cpp#516-519
Bug 1742540 Comment 3 Edit History
Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.
Patch seems simple but the root cause is complicated, I try to describe it as brief as possible. When building ClonedMessageData of a Blob, gecko will clone the inputStream [1] and wrap it as a RemoteLazyStream in serialize phase. If the inputStream is not cloneable (i.e. FileStream), NS_CloneInputStream [2] creates a new pipe and return two cloned stream (reader and writer). Then first, clone reader stream, wrap this cloned inputStream as RemoteLazyStream, serialize it with IPC. Second, copy the source data to writer stream. To start the copy phase, copier holds references of writer stream (this adds two extra refcnt of pipe). And process data copy iff there is read request from child side. Then close the writer stream and release them when done with copy. When child has done with RemoteLazyStream, RemoteLazyInputStreamParent will try to release the cloned inputStream, closing itself explicitly [3]. Logic in nsPipe::OnInputStreamException [3] shows that gecko only shutdown the entire pipe iff there is one stream left and it is the given stream. So here we will not shutdown the pipe because there are two inputStreams left, one is the original inputStream, the other is the cloned inputStream. The cloned inputStream will be closed by ActorDestroy of RemoteLazyInputStreamParent and decrease one refcnt of this pipe. In nsPipe::Release [4], shows that gecko only release the original inputStream iff the refcnt of pipe decrease to one. In the scenario where no read request from child, copier never finishes, two extra refcnt of pipe hold by copier, original inputStream will not be release. Thus, this is why I try to close the inputStream (a.k.a. the original inputStream) in advance when destructing StreamBlobImpl. [1] https://searchfox.org/mozilla-central/source/dom/file/StreamBlobImpl.cpp#73 [2] https://searchfox.org/mozilla-central/source/xpcom/io/nsStreamUtils.cpp#859 [3] https://searchfox.org/mozilla-central/source/xpcom/io/nsPipe3.cpp#905-910 [4] https://searchfox.org/mozilla-central/source/xpcom/io/nsPipe3.cpp#516-519