Crash in [@ mozilla::dom::ReadableStreamReaderGenericRelease]
Categories
(Core :: DOM: Streams, defect, P2)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox-esr102 | --- | unaffected |
| firefox110 | --- | wontfix |
| firefox111 | + | wontfix |
| firefox112 | --- | fixed |
People
(Reporter: aryx, Assigned: peterv)
References
(Regression)
Details
(Keywords: crash, regression)
Crash Data
Attachments
(1 file)
186 crashes from 129 installations of Firefox 110.0, version 109.0 has no reports with this signature.
Is this a regression from bug 1809673?
[Tracking Requested - why for this release]: medium volume crash introduced in Firefox 110.0
Crash report: https://crash-stats.mozilla.org/report/index/664ed8fa-e617-4409-b9d9-64b4a0230223
Reason: EXCEPTION_ACCESS_VIOLATION_READ
Top 10 frames of crashing thread:
0 xul.dll mozilla::RefPtrTraits<mozilla::dom::ReadableStream>::AddRef mfbt/RefPtr.h:49
0 xul.dll RefPtr<mozilla::dom::ReadableStream>::ConstRemovingRefPtrTraits<mozilla::dom::ReadableStream>::AddRef mfbt/RefPtr.h:380
0 xul.dll RefPtr<mozilla::dom::ReadableStream>::RefPtr mfbt/RefPtr.h:109
0 xul.dll mozilla::dom::ReadableStreamReaderGenericRelease dom/streams/ReadableStreamDefaultReader.cpp:272
1 xul.dll mozilla::dom::ReadableStreamDefaultReaderRelease dom/streams/ReadableStreamBYOBReader.cpp:306
2 xul.dll mozilla::dom::ReadableStream::IteratorReturn dom/streams/ReadableStream.cpp:948
3 xul.dll mozilla::dom::binding_detail::AsyncIterableIteratorWithReturn<mozilla::dom::ReadableStream>::GetReturnPromise dom/bindings/IterableIterator.h:402
4 xul.dll mozilla::dom::binding_detail::AsyncIterableReturnImpl::ReturnSteps dom/bindings/IterableIterator.cpp:257
5 xul.dll mozilla::dom::binding_detail::AsyncIterableReturnImpl::Return::<lambda_0>::operator const dom/bindings/IterableIterator.cpp:290
5 xul.dll mozilla::dom:: dom/promise/Promise-inl.h:205
Comment 1•3 years ago
•
|
||
The first report happened in Jan 8, before bug 1809673 landed. Looks more like bug 1734244 per the stack.
Edit: Actually in Jan 5. https://crash-stats.mozilla.org/report/index/9d73790a-4f6f-4755-a975-62f8e0230105
Comment 2•3 years ago
|
||
1 xul.dll mozilla::dom::ReadableStreamDefaultReaderRelease dom/streams/ReadableStreamBYOBReader.cpp:306
This doesn't makes sense, why is ReadableStreamDefaultReaderRelease in ReadableStreamBYOBReader.cpp?
Comment 3•3 years ago
•
|
||
The crash stack somehow shows ReadableStreamBYOBReaderRelease in the name of ReadableStreamDefaultReaderRelease. Can it be a compiler error? https://crash-stats.mozilla.org/report/index/2f173892-df0c-4172-9800-d938b0230224
Comment 4•3 years ago
|
||
Not all reports do that, btw... https://crash-stats.mozilla.org/report/index/fe3f0328-f70a-4324-b43b-e54750230108#tab-details
Updated•3 years ago
|
Comment 5•3 years ago
|
||
For now I have no idea how to investigate this without a repro. I found that BodyStream can cause an unexpected change to ReadableStream and that might be related here: Bug 1818387.
Updated•3 years ago
|
Comment 6•3 years ago
|
||
The bug is marked as tracked for firefox111 (beta). We have limited time to fix this, the soft freeze is in 10 days. However, the bug still isn't assigned.
:jstutte, could you please find an assignee for this tracked bug? If you disagree with the tracking decision, please talk with the release managers.
For more information, please visit auto_nag documentation.
Comment 7•3 years ago
|
||
IIUC from how mStream is defined and used it seems, we can find it nullptr if a ReadableStreamGenericReader has been constructed but SetStream has never been called.
The stack seems to point to this assignment but cracking a dump up with VS seems to show the actual nullptr access is from the line below (ignoring the MOZ_ASSERT).
I assume we should not just assert here but also bail out/throw an error?
Comment 8•3 years ago
|
||
Maybe I should request a dump access...
Not having a stream in a reader means something very wrong happened, throwing an error should be a last resort. It means either it's not initialized at all (oh no) or it's being released twice (oh no no).
Comment 9•3 years ago
|
||
:evilpie, since you are the author of the regressor, bug 1734244, could you take a look?
For more information, please visit auto_nag documentation.
Comment 10•3 years ago
|
||
I am really quite busy the next two weeks, I hope Kagami figures this out.
Comment 11•3 years ago
|
||
Hi Tom, Kagami is on PTO the next two weeks...
Taking another look, from here it seems, mStream == nullptr can occur:
- right after initialization if
SetStreamwas never called (unlikely due to the asserts?) - after
ReadableStreamReaderGenericReleasehas been called, which seems to have quite some different call-paths, such that I would not be too surprised if we see it called twice?
Should we harden ReadableStreamReaderGenericRelease (or some of its callers) against re-entrance?
Comment 12•3 years ago
|
||
right after initialization if SetStream was never called
The init step involves SetStream, so no 🤔
Comment 13•3 years ago
•
|
||
I guess we could harden ReadableStream::IteratorReturn against a null stream. That function really shouldn't be called after the iteration is already finished (and thus the stream is closed). I think that either indicates a spec issue or some problem with the implementation of iterators as provided by the WebIDL bindings. Maybe Peter has some idea?
| Assignee | ||
Comment 14•3 years ago
|
||
IteratorReturn should only be called once (through GetReturnPromise). We follow the spec here: https://searchfox.org/mozilla-central/source/dom/bindings/IterableIterator.cpp#237,252,257 I don't see how it could be called multiple times for the same iterator. I don't know much about the streams implementation, so not sure what else could be going wrong, but note that there can be multiple iterators for the same object.
Comment 15•3 years ago
|
||
(In reply to Peter Van der Beken [:peterv] from comment #14)
but note that there can be multiple iterators for the same object.
Could that mean that the first iterator return wins and the second looses? Must the object track usage by iterators and cleanup only when the last usage has gone?
| Assignee | ||
Comment 16•3 years ago
|
||
(In reply to Jens Stutte [:jstutte] from comment #15)
Could that mean that the first iterator return wins and the second looses? Must the object track usage by iterators and cleanup only when the last usage has gone?
I don't know what you mean by win and lose. WebIDL just defines when iterators are created and there is nothing that prevents multiple iterators being alive at the same time. It's up to individual specs to define how those iterators should function. I assume that the streams spec defines this.
Comment 17•3 years ago
|
||
You can have only one reader per ReadableStream, so you can in theory only construct one iterator as well.
Comment 18•3 years ago
•
|
||
I tried to human-fuzz but failed to repro this. The only way I can imagine is to trick BodyStream to call JS involving synchronous XHR via EnqueueNative (AFAIK only piping can do this, and can unexpectedly close the stream while still reading) while the async iteration is happening, which should be fixed by bug 1818387 if it's even possible.
Edit: Sorry, bug 1818387 will fix the crash but not the sudden closing.
Comment 19•3 years ago
|
||
Picking random crash report here always shows mozilla::dom::BodyStream::OnInputStreamReady and ~nsAutoMicroTask so that must be it, but not sure how exactly 🙃
Comment 20•3 years ago
|
||
Perhaps smaug can handle the nsAutoMicroTask thing, that's probably better than trying to get a repro of the crash.
| Assignee | ||
Comment 21•3 years ago
|
||
(In reply to Tom S [:evilpie] from comment #17)
You can have only one reader per ReadableStream, so you can in theory only construct one iterator as well.
After reading the spec, it seems like creating an iterator while there is one alive already should fail, because IsReadableStreamLocked will return true (https://streams.spec.whatwg.org/#set-up-readable-stream-default-reader and https://searchfox.org/mozilla-central/source/dom/streams/ReadableStreamDefaultReader.cpp#413-418).
Comment 22•3 years ago
|
||
(In reply to Kagami pto-until-March-10 [:saschanaz] from comment #19)
Picking random crash report here always shows mozilla::dom::BodyStream::OnInputStreamReady and ~nsAutoMicroTask so that must be it, but not sure how exactly 🙃
I don't see that ~nsAutoMicroTask particularly interesting. Without nsAutoMicroTask we just might run microtasks just sooner.
| Assignee | ||
Comment 23•3 years ago
|
||
(In reply to Jens Stutte [:jstutte] from comment #11)
- after
ReadableStreamReaderGenericReleasehas been called, which seems to have quite some different call-paths, such that I would not be too surprised if we see it called twice?
I've gone through the calls to ReadableStreamDefaultReaderRelease in ReadableStream.cpp, I think those are ok. mozilla::dom::IteratorReadRequest::CloseSteps/ErrorSteps either reject the promise or resolve it with the end of iteration-value. That should always cause the iterator to be set to the finished state. After that we shouldn't call back into the ReadableStream code anymore, we always check for the finished state before.
| Assignee | ||
Comment 24•3 years ago
|
||
I don't suppose there's a way for script to get its hands on the default stream reader that is created for the async iterator? It would then for example be possible for it to call ReadableStreamDefaultReader.releaseLock.
Comment 25•3 years ago
|
||
:smaug Hey, could you set a severity on this issue? Do we want to land something for 111?
Comment 26•3 years ago
|
||
Yes, we do need to fix this somehow, I think, even in 111. This is rather frequent.
(But I'm not yet at all familiar with AsyncIterableIteratorWithReturn)
Comment 27•3 years ago
|
||
This is a reminder regarding comment #6!
The bug is marked as tracked for firefox111 (beta). We have limited time to fix this, the soft freeze is in 3 days. However, the bug still isn't assigned.
Comment 28•3 years ago
|
||
peterv, I think you said you're looking into this.
Comment 29•3 years ago
|
||
This is a reminder regarding comment #6!
The bug is marked as tracked for firefox111 (beta). We have limited time to fix this, the soft freeze is in 2 days. However, the bug still isn't assigned.
Comment 30•3 years ago
|
||
This is a reminder regarding comment #6!
The bug is marked as tracked for firefox111 (beta). We have limited time to fix this, the soft freeze is in a day. However, the bug still isn't assigned.
| Assignee | ||
Comment 31•3 years ago
|
||
Updated•3 years ago
|
| Assignee | ||
Comment 32•3 years ago
|
||
I added a null-check, preceded by a MOZ_DIAGNOSTIC_ASSERT. That should make the crash go away on beta and release. I've filed a followup bug (bug 1821169) to figure out what is actually going on.
Comment 33•3 years ago
|
||
Comment 34•3 years ago
|
||
| bugherder | ||
Comment 35•3 years ago
|
||
The patch landed in nightly and beta is affected.
:peterv, is this bug important enough to require an uplift?
- If yes, please nominate the patch for beta approval.
- If no, please set
status-firefox111towontfix.
For more information, please visit auto_nag documentation.
Comment 36•3 years ago
|
||
:peterv re: comment 35 - is this suitable for uplift in for a dot release ridealong?
Comment 37•3 years ago
|
||
Setting 111 to wontfix, this can ride the train with 112.
| Assignee | ||
Updated•2 years ago
|
Description
•