Hit MOZ_CRASH(Promise not thread-safe) at /xpcom/base/nsISupportsImpl.cpp:43
Categories
(Core :: DOM: Workers, defect, P3)
Tracking
()
People
(Reporter: jkratzer, Unassigned, NeedInfo)
References
(Blocks 1 open bug)
Details
(Keywords: testcase-wanted, Whiteboard: dom-lws-bugdash-triage)
Attachments
(2 files, 1 obsolete file)
Found while fuzzing mozilla-try rev 8b146d6f10c9 (built with: --enable-address-sanitizer --enable-fuzzing).
Unfortunately, the testcase used to initially identify this issue does not reproduce. Hopefully the stack trace will shed some light on what's happening here.
Hit MOZ_CRASH(Promise not thread-safe) at /xpcom/base/nsISupportsImpl.cpp:43
=================================================================
==7221==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000001 (pc 0x7f1f332eb185 bp 0x7ffccfa0e310 sp 0x7ffccfa0e300 T0)
==7221==The signal is caused by a WRITE memory access.
==7221==Hint: address points to the zero page.
#0 0x7f1f332eb185 in MOZ_Crash /builds/worker/workspace/obj-build/dist/include/mozilla/Assertions.h:261:3
#1 0x7f1f332eb185 in nsAutoOwningThread::AssertCurrentThreadOwnsMe(char const*) const /gecko/xpcom/base/nsISupportsImpl.cpp:43:5
#2 0x7f1f3328e9e9 in AssertOwnership<24> /builds/worker/workspace/obj-build/dist/include/nsISupportsImpl.h:60:5
#3 0x7f1f3328e9e9 in mozilla::dom::Promise::Release() /builds/worker/workspace/obj-build/dist/include/mozilla/dom/Promise.h:53:3
#4 0x7f1f36b859a2 in Release /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:50:40
#5 0x7f1f36b859a2 in Release /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:381:36
#6 0x7f1f36b859a2 in ~RefPtr /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:81:7
#7 0x7f1f36b859a2 in mozilla::dom::BodyConsumer::~BodyConsumer() /gecko/dom/base/BodyConsumer.cpp:381:29
#8 0x7f1f36b84e05 in Release /gecko/dom/base/BodyConsumer.cpp:820:1
#9 0x7f1f36b84e05 in Release /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:50:40
#10 0x7f1f36b84e05 in Release /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:381:36
#11 0x7f1f36b84e05 in RefPtr<mozilla::dom::BodyConsumer>::~RefPtr() /builds/worker/workspace/obj-build/dist/include/mozilla/RefPtr.h:81:7
#12 0x7f1f36bab775 in ~ConsumeBodyDoneObserver /gecko/dom/base/BodyConsumer.cpp:263:38
#13 0x7f1f36bab775 in mozilla::dom::(anonymous namespace)::ConsumeBodyDoneObserver::Release() /gecko/dom/base/BodyConsumer.cpp:269:1
#14 0x7f1f338d061e in assign_assuming_AddRef /builds/worker/workspace/obj-build/dist/include/nsCOMPtr.h:377:7
#15 0x7f1f338d061e in assign_assuming_AddRef /builds/worker/workspace/obj-build/dist/include/nsCOMPtr.h:400:20
#16 0x7f1f338d061e in operator= /builds/worker/workspace/obj-build/dist/include/nsCOMPtr.h:696:5
#17 0x7f1f338d061e in mozilla::net::nsStreamLoader::OnStopRequest(nsIRequest*, nsresult) /gecko/netwerk/base/nsStreamLoader.cpp:98:15
#18 0x7f1f3380d82b in nsInputStreamPump::OnStateStop() /gecko/netwerk/base/nsInputStreamPump.cpp:636:16
#19 0x7f1f3380bd7e in nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream*) /gecko/netwerk/base/nsInputStreamPump.cpp:381:21
#20 0x7f1f3339d1bd in mozilla::NonBlockingAsyncInputStream::RunAsyncWaitCallback(mozilla::NonBlockingAsyncInputStream::AsyncWaitRunnable*, already_AddRefed<nsIInputStreamCallback>) /gecko/xpcom/io/NonBlockingAsyncInputStream.cpp:398:13
#21 0x7f1f3339bb2e in mozilla::NonBlockingAsyncInputStream::AsyncWaitRunnable::Run() /gecko/xpcom/io/NonBlockingAsyncInputStream.cpp:33:14
#22 0x7f1f334ca422 in mozilla::ThrottledEventQueue::Inner::ExecuteRunnable() /gecko/xpcom/threads/ThrottledEventQueue.cpp:254:22
#23 0x7f1f334c23ff in mozilla::ThrottledEventQueue::Inner::Executor::Run() /gecko/xpcom/threads/ThrottledEventQueue.cpp:81:15
#24 0x7f1f334c4292 in mozilla::RunnableTask::Run() /gecko/xpcom/threads/TaskController.cpp:468:16
#25 0x7f1f33489b8d in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /gecko/xpcom/threads/TaskController.cpp:771:26
#26 0x7f1f334870e8 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) /gecko/xpcom/threads/TaskController.cpp:607:15
#27 0x7f1f334877f9 in mozilla::TaskController::ProcessPendingMTTask(bool) /gecko/xpcom/threads/TaskController.cpp:391:36
#28 0x7f1f334cc691 in operator() /gecko/xpcom/threads/TaskController.cpp:124:37
#29 0x7f1f334cc691 in mozilla::detail::RunnableFunction<mozilla::TaskController::InitializeInternal()::$_0>::Run() /gecko/xpcom/threads/nsThreadUtils.h:531:5
#30 0x7f1f334a9e87 in nsThread::ProcessNextEvent(bool, bool*) /gecko/xpcom/threads/nsThread.cpp:1195:16
#31 0x7f1f334b506c in NS_ProcessNextEvent(nsIThread*, bool) /gecko/xpcom/threads/nsThreadUtils.cpp:467:10
#32 0x7f1f349cbc7f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /gecko/ipc/glue/MessagePump.cpp:85:21
#33 0x7f1f3484b9a1 in RunInternal /gecko/ipc/chromium/src/base/message_loop.cc:331:10
#34 0x7f1f3484b9a1 in RunHandler /gecko/ipc/chromium/src/base/message_loop.cc:324:3
#35 0x7f1f3484b9a1 in MessageLoop::Run() /gecko/ipc/chromium/src/base/message_loop.cc:306:3
#36 0x7f1f3b8189e7 in nsBaseAppShell::Run() /gecko/widget/nsBaseAppShell.cpp:137:27
#37 0x7f1f40546d7f in XRE_RunAppShell() /gecko/toolkit/xre/nsEmbedFunctions.cpp:870:20
#38 0x7f1f3484b9a1 in RunInternal /gecko/ipc/chromium/src/base/message_loop.cc:331:10
#39 0x7f1f3484b9a1 in RunHandler /gecko/ipc/chromium/src/base/message_loop.cc:324:3
#40 0x7f1f3484b9a1 in MessageLoop::Run() /gecko/ipc/chromium/src/base/message_loop.cc:306:3
#41 0x7f1f40545fb3 in XRE_InitChildProcess(int, char**, XREChildData const*) /gecko/toolkit/xre/nsEmbedFunctions.cpp:707:34
#42 0x55d343a3bf9d in content_process_main(mozilla::Bootstrap*, int, char**) /gecko/browser/app/../../ipc/contentproc/plugin-container.cpp:57:28
#43 0x55d343a3c3c8 in main /gecko/browser/app/nsBrowserApp.cpp:327:18
#44 0x7f1f57be80b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
#45 0x55d34398b069 in _start (/home/worker/builds/try-20220117185637-fuzzing-asan-opt/firefox+0x5d069)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /builds/worker/workspace/obj-build/dist/include/mozilla/Assertions.h:261:3 in MOZ_Crash
==7221==ABORTING
Reporter | ||
Comment 1•3 years ago
|
||
Comment 2•3 years ago
|
||
Given that this was a DOM Streams build, I'm marking it as a ship-blocker for DOM Streams until we know more.
Comment 3•3 years ago
|
||
Jason: Despite the lack of reproduction, could you post the test case? Below I'm trying to do some reasoning out of what's going on, and seeing the test case would help prove or disprove my suspision. I suspect this isn't a failure limited to DOM Streams.
Analysis By Stacktrace
So we crash while destroying a promise held by BodyConsumer
.
There is only one promise held by BodyConsumer
, so we have to be destroying BodyConsumer::mConsumePromise
.
Inspecting how mConsumePromise
is used, it is only ever set in the constructor, nulled out, or std::move
ed into a local. So the promise must be the one provided to the constructor.
There's only one call to the BodyConsumer
constructor, inside of BodyConsumer::Create
-- and this function also creates the Promise. So we know that BodyConsumer
and the mConsumePromise
must have been created on the same thread; and since the observed crash is happening while running on main thread (unless DoExecuteNextTaskOnlyMainThreadInternal
is lying to me) we know that BodyConsumer::Create
must have been created off the main thread.
The only caller to BodyConsumer::Create
comes from Blob::ConsumeBody
-- this is used to power Blob::Text
and Blob::ArrayBuffer
, both of which are defined by the Blob WebIDL
So if I had to guess, this failure has to do with a blob being created on a worker. Then, there's something to do with an nsInputStreamPump calling the listener's OnStopRequest
on the main thread, which frees the observer, which in turn frees the BodyConsumer
.
This is likely tricky to reproduce because the promise has to be collectable at this point, which can only happen if the Promise wrapper has already been collected, so you need to have a GC having occurred, then have the nsInputStreamPump call OnStopRequest
.
Of course, I understand nothing of how to fix this; but I am very skeptical this is a DOM streams problem directly.
Going to move this to DOM Workers as a guess... not 100% sure though.
Reporter | ||
Comment 4•3 years ago
|
||
Testcase found while fuzzing mozilla-try rev 8b146d6f10c9 (built with: --enable-address-sanitizer --enable-fuzzing).
As the testcase is not reproducible, it is has not been minimized. Please let me know if you have any questions.
Reporter | ||
Comment 5•3 years ago
|
||
Reporter | ||
Comment 6•3 years ago
|
||
Reporter | ||
Updated•3 years ago
|
Reporter | ||
Updated•3 years ago
|
Comment 7•3 years ago
|
||
Oh wow; you're not wrong about an un-reduced case; neverthless, I do spot some use of workers and some use of Blob.prototype.arrayBuffer
in the worker...
Comment 8•3 years ago
•
|
||
Looking at BodyConsumer::ContinueConsumeBlobBody
I wonder if we miss a ReleaseObject();
in that blob failure case? (Even if so it might not be the reason for this, of course, I am just looking at the code.)
Updated•3 years ago
|
Comment hidden (Intermittent Failures Robot) |
Updated•4 months ago
|
Description
•