-
Notifications
You must be signed in to change notification settings - Fork 349
Description
What is this issue about?
The WASM PHP crashes in chrome. It does not crash in Firefox, Safari, and node.js.
See the minimal reproduction in bug-reproduction.zip. It consists of two HTML files: breaks_here.html and works_here.html. The first one demonstrates the problem in the worker and the second one shows that the issue does not occur in the main thread crashes too, although less frequently.
The issue is the most apparent inside of a webworker, but it also exists when WASM is initialized in the main browser thread. The code below is enough to trigger the crash. Note we don't even run any wasm code, just instantiate the module:
(() => {
// src/web/web-worker.js
console.log("[WebWorker] Spawned");
var wasmTable = new WebAssembly.Table({
initial: 1090,
maximum: 1090,
element: "anyfunc"
});
var WASM_PAGE_SIZE = 65536;
var INITIAL_INITIAL_MEMORY = 1073741824;
var wasmMemory = new WebAssembly.Memory({
initial: INITIAL_INITIAL_MEMORY / WASM_PAGE_SIZE
});
var info = {
env: {
_zend_empty_array2: 1,
tempDoublePtr: 2303696,
"__memory_base": 1024,
__table_base: 0,
memory: wasmMemory,
table: wasmTable
},
global: { NaN: NaN, Infinity: Infinity },
asm2wasm: {
"f64-rem"() {
}
}
};
fetch("updated.wasm").then(async (response) => {
WebAssembly.instantiate(
await response.arrayBuffer(),
info
).then(() => {
console.log("Instantiated!");
});
console.log("Called instantiate");
});
console.log("Called fetch", { info });
})();
Chromium debugging findings
The Chromium team shared the following stack trace proving this is an out of memory problem:
Magic Signature >> [Out of Memory] v8::internal::Zone::NewExpand
Stack Trace >>
Thread 26 ThreadPoolForegroundWorker (id: 0x005aad74)crashedMAGIC SIGNATURE THREADcontent_copy
0x00000001211dbf58(Google Chrome Framework -oom.cc:58)partition_alloc::internal::OnNoMemoryInternal(unsigned long)
0x00000001211dbf68(Google Chrome Framework -oom.cc:65)partition_alloc::TerminateBecauseOutOfMemory(unsigned long)
0x00000001211dbf85(Google Chrome Framework -oom.cc:75)partition_alloc::internal::OnNoMemory(unsigned long)
0x00000001246e95b2(Google Chrome Framework -partitions.cc:323)WTF::PartitionsOutOfMemoryUsing512M(unsigned long)
0x00000001246e948c(Google Chrome Framework -partitions.cc:448)WTF::Partitions::HandleOutOfMemory(unsigned long)
0x00000001211dd8b3(Google Chrome Framework -partition_root.cc:619)partition_alloc::PartitionRoot<true>::OutOfMemory(unsigned long)
0x00000001211dca8a(Google Chrome Framework -partition_bucket.cc:48)void partition_alloc::internal::(anonymous namespace)::PartitionOutOfMemoryMappingFailure<true>(partition_alloc::PartitionRoot<true>*, unsigned long)
0x000000011dfa61de(Google Chrome Framework -partition_bucket.cc:691)partition_alloc::internal::PartitionBucket<true>::SlowPathAlloc(partition_alloc::PartitionRoot<true>*, unsigned int, unsigned long, unsigned long, bool*)
0x000000011dfae2cc(Google Chrome Framework -partition_root.h:1072)base::AllocNonQuarantinable(unsigned long)
0x000000011df36397(Google Chrome Framework -allocation.cc:141)v8::internal::Zone::NewExpand(unsigned long)
0x0000000120a961d4(Google Chrome Framework + 0x0000000002b851d4)std::Cr::vector<v8::internal::compiler::Node*, v8::internal::ZoneAllocator<v8::internal::compiler::Node*>>::vector(std::Cr::vector<v8::internal::compiler::Node*, v8::internal::ZoneAllocator<v8::internal::compiler::Node*>> const&)
0x0000000122d2a138(Google Chrome Framework + 0x0000000004e19138)v8::internal::wasm::(anonymous namespace)::WasmGraphBuildingInterface::Split(v8::internal::Zone*, v8::internal::wasm::(anonymous namespace)::SsaEnv*)
0x0000000122d2bfc5(Google Chrome Framework + 0x0000000004e1afc5)v8::internal::wasm::(anonymous namespace)::WasmGraphBuildingInterface::BrOrRet(v8::internal::wasm::WasmFullDecoder<(v8::internal::wasm::Decoder::ValidateFlag)2, v8::internal::wasm::(anonymous namespace)::WasmGraphBuildingInterface, (v8::internal::wasm::DecodingMode)0>*, unsigned int, unsigned int)
0x0000000122d1efc4(Google Chrome Framework + 0x0000000004e0dfc4)v8::internal::wasm::WasmFullDecoder<(v8::internal::wasm::Decoder::ValidateFlag)2, v8::internal::wasm::(anonymous namespace)::WasmGraphBuildingInterface, (v8::internal::wasm::DecodingMode)0>::DecodeBrTable(v8::internal::wasm::WasmFullDecoder<(v8::internal::wasm::Decoder::ValidateFlag)2, v8::internal::wasm::(anonymous namespace)::WasmGraphBuildingInterface, (v8::internal::wasm::DecodingMode)0>*, v8::internal::wasm::WasmOpcode)
0x0000000122d1b301(Google Chrome Framework + 0x0000000004e0a301)v8::internal::wasm::WasmFullDecoder<(v8::internal::wasm::Decoder::ValidateFlag)2, v8::internal::wasm::(anonymous namespace)::WasmGraphBuildingInterface, (v8::internal::wasm::DecodingMode)0>::Decode()
0x0000000122d1ab36(Google Chrome Framework + 0x0000000004e09b36)v8::internal::wasm::BuildTFGraph(v8::internal::AccountingAllocator*, v8::internal::wasm::WasmFeatures const&, v8::internal::wasm::WasmModule const*, v8::internal::compiler::WasmGraphBuilder*, v8::internal::wasm::WasmFeatures*, v8::internal::wasm::FunctionBody const&, std::Cr::vector<v8::internal::compiler::WasmLoopInfo, std::Cr::allocator<v8::internal::compiler::WasmLoopInfo>>*, v8::internal::compiler::NodeOriginTable*, int, v8::internal::wasm::InlinedStatus)
0x0000000122ee6b35(Google Chrome Framework + 0x0000000004fd5b35)v8::internal::compiler::ExecuteTurbofanWasmCompilation(v8::internal::wasm::CompilationEnv*, v8::internal::wasm::WireBytesStorage const*, v8::internal::wasm::FunctionBody const&, int, v8::internal::Counters*, v8::internal::wasm::AssemblerBufferCache*, v8::internal::wasm::WasmFeatures*)
0x000000012082f8b6(Google Chrome Framework + 0x000000000291e8b6)v8::internal::wasm::WasmCompilationUnit::ExecuteCompilation(v8::internal::wasm::CompilationEnv*, v8::internal::wasm::WireBytesStorage const*, v8::internal::Counters*, v8::internal::wasm::AssemblerBufferCache*, v8::internal::wasm::WasmFeatures*)
0x00000001207fc41d(Google Chrome Framework + 0x00000000028eb41d)v8::internal::wasm::(anonymous namespace)::ExecuteCompilationUnits(std::Cr::weak_ptr<v8::internal::wasm::NativeModule>, v8::internal::Counters*, v8::JobDelegate*, v8::internal::wasm::(anonymous namespace)::CompileBaselineOnly)
0x0000000120a96633(Google Chrome Framework + 0x0000000002b85633)v8::internal::wasm::(anonymous namespace)::BackgroundCompileJob::Run(v8::JobDelegate*) (.886d8138751ea58144f90ddffe92ca79)
0x0000000125c6e110(Google Chrome Framework -v8_platform.cc:458)base::internal::Invoker<base::internal::BindState<gin::V8Platform::CreateJob(v8::TaskPriority, std::Cr::unique_ptr<v8::JobTask, std::Cr::default_delete<v8::JobTask>>)::$_0, std::Cr::unique_ptr<v8::JobTask, std::Cr::default_delete<v8::JobTask>>>, void (base::JobDelegate*)>::Run(base::internal::BindStateBase*, base::JobDelegate*)
0x000000012549ec24(Google Chrome Framework -callback.h:263)base::internal::Invoker<base::internal::BindState<base::internal::JobTaskSource::JobTaskSource(base::Location const&, base::TaskTraits const&, base::RepeatingCallback<void (base::JobDelegate*)>, base::RepeatingCallback<unsigned long (unsigned long)>, base::internal::PooledTaskRunnerDelegate*)::$_0, base::internal::UnretainedWrapper<base::internal::JobTaskSource>>, void ()>::Run(base::internal::BindStateBase*)
0x000000011e3e3a06(Google Chrome Framework -callback.h:145)base::internal::TaskTracker::RunSkipOnShutdown(base::internal::Task&, base::TaskTraits const&, base::internal::TaskSource*, base::SequenceToken const&)
0x000000011e58a828(Google Chrome Framework -task_tracker.cc:724)base::internal::TaskTracker::RunAndPopNextTask(base::internal::RegisteredTaskSource)
0x000000011e6e8d9d(Google Chrome Framework -worker_thread.cc:448)base::internal::WorkerThread::RunWorker()
0x00000001238739dc(Google Chrome Framework -worker_thread.cc:335)base::internal::WorkerThread::RunPooledWorker()
0x000000011f091c56(Google Chrome Framework -worker_thread.cc:315)base::internal::WorkerThread::ThreadMain()
0x000000011ee21522(Google Chrome Framework -platform_thread_posix.cc:101)base::(anonymous namespace)::ThreadFunc(void*)
0x00007ff81a49b4e0(libsystem_pthread.dylib + 0x000064e0)
0x00007ff81a496f6a(libsystem_pthread.dylib + 0x00001f6a)
Other Chromium findings
I did some debugging before they shared that stack trace. The list below is less relevant than the specific details in the stack trace above, but I'm still posting it here for posterity:
- The easiest way to trigger the crash is to open devtools and keep triggering "clear cache and refresh," but it also does crash without devtools – it's just much harder to trigger it. These could be two different problems :(
- The crash does happen when the service worker isn't being registered, which tells me it is not related to service workers at all.
- It always crashes with error code 5 which means
TERMINATION_STATUS_PROCESS_CRASHED
. - I attached a debugger and did not get much more information than error code 5:
- The debugger (lldb) attached to a healthy Chromium process. I didn't manage to inspect the crashing process right before the crash. I hoped
valgrind
would help, but it won't run on Mac. - Crashpad logs a minidump, but sadly does not forward it to Mac system crash browser like it does with
about:crash
and other crashes.This means you need to manually symbolize it to extract any useful information and I didn't get there yet.Older Chromium used breakpad where manual symbolization was needed. Modern Chromium uses crashpad which can be symbolized as follows:
minidump-stackwalk gets its symbols from google-breakpad symbol files. Symbol files are a plain-text format intended to unify the contents of various platform-specific debuginfo/unwinding formats like PE32 Unwinding Tables, Dwarf CFI, Macho Compact Unwinding Info, etc.
To generate those files from your build artifacts, use either Mozilla's dump_syms (recommended) or google-breakpad's dump_syms.
- Chromium logs the same stacktrace after this crash. However, I wasn't able to attach a debugger on V8_Fatal as the execution wouldn't stop there. I will keep trying.
#
# Fatal error in ../../v8/src/debug/debug-interface.cc, line 352
# Debug check failed: !isolate->is_execution_terminating().
#
#
#
#FailureMessage Object: 0x700009b7bc60[33312:259:0929/223909.968925:VERBOSE1:node.cc(1175)] OnUpdatePreviousPeer port: E64B3F19A9C61113.8955D49085231446 changing to AA7F7063054BDC96.DF5C9FB08811A500, port: E2387E855C7DDE33.6435B60F182B2A50 => BFD53B2279161D17.D245A7E2302529BE
[33609:18179:0929/223909.969410:VERBOSE1:node.cc(1175)] OnUpdatePreviousPeer port: BFD53B2279161D17.D245A7E2302529BE changing to 6975933DD5F27952.C20103EDCDFD9098, port: E2387E855C7DDE33.6435B60F182B2A50 => E64B3F19A9C61113.8955D49085231446
[33614:259:0929/223909.971940:VERBOSE1:paint_controller.cc(709)] PaintController::FinishCycle() completed
0 libbase.dylib 0x000000010d65f21c base::debug::CollectStackTrace(void**, unsigned long) + 44
1 libbase.dylib 0x000000010d2f6978 base::debug::StackTrace::StackTrace(unsigned long) + 72
2 libbase.dylib 0x000000010d2f69fd base::debug::StackTrace::StackTrace(unsigned long) + 29
3 libbase.dylib 0x000000010d2f69d5 base::debug::StackTrace::StackTrace() + 37
4 libgin.dylib 0x00000001a7b79d1b gin::(anonymous namespace)::PrintStackTrace() + 59
5 libv8_libbase.dylib 0x0000000119cd80f1 V8_Fatal(char const*, int, char const*, ...) + 337
6 libv8_libbase.dylib 0x0000000119cd78e5 v8::base::(anonymous namespace)::DefaultDcheckHandler(char const*, int, char const*) + 21
7 libv8.dylib 0x00000001d4423933 v8::debug::SetBreakPointsActive(v8::Isolate*, bool) + 291
8 libv8.dylib 0x00000001d5558df3 v8_inspector::V8DebuggerAgentImpl::disable() + 419
9 libv8.dylib 0x00000001d5587bca v8_inspector::V8InspectorSessionImpl::~V8InspectorSessionImpl() + 346
10 libv8.dylib 0x00000001d5587d9e v8_inspector::V8InspectorSessionImpl::~V8InspectorSessionImpl() + 14
11 libblink_core.dylib 0x00000001df137d4c std::Cr::default_delete<v8_inspector::V8InspectorSession>::operator()[abi:v16000](v8_inspector::V8InspectorSession*) const + 44
12 libblink_core.dylib 0x00000001df12792a std::Cr::unique_ptr<v8_inspector::V8InspectorSession, std::Cr::default_delete<v8_inspector::V8InspectorSession>>::reset[abi:v16000](v8_inspector::V8InspectorSession*) + 106
13 libblink_core.dylib 0x00000001df126c08 blink::DevToolsSession::Detach() + 1288
[33312:259:0929/223909.985578:VERBOSE1:node.cc(1175)] OnUpdatePreviousPeer port: 49CA70FD9D9D7B94.3536F4AFEA56CA2C changing to AA7F7063054BDC96.DF5C9FB08811A500, port: 64987F6ACCED8335.8529510F6C84227 => 12FA36F038112775.2F840886748B53FC
14 libblink_core.dylib 0x00000001df10b64f blink::DevToolsAgent::Dispose() + 527
15 libblink_core.dylib 0x00000001df508b77 blink::WorkerInspectorController::Dispose() + 183
16 libblink_core.dylib 0x00000001e08501ce blink::WorkerThread::PerformShutdownOnWorkerThread() + 526
17 libblink_core.dylib 0x00000001e085726a void base::internal::FunctorTraits<void (blink::WorkerThread::*)(), void>::Invoke<void (blink::WorkerThread::*)(), blink::WorkerThread*>(void (blink::WorkerThread::*)(), blink::WorkerThread*&&) + 122
18 libblink_core.dylib 0x00000001e08571e4 void base::internal::InvokeHelper<false, void>::MakeItSo<void (blink::WorkerThread::*)(), blink::WorkerThread*>(void (blink::WorkerThread::*&&)(), blink::WorkerThread*&&) + 52
19 libblink_core.dylib 0x00000001e0857188 void base::internal::Invoker<base::internal::BindState<void (blink::WorkerThread::*)(), WTF::CrossThreadUnretainedWrapper<blink::WorkerThread>>, void ()>::RunImpl<void (blink::WorkerThread::*)(), std::Cr::tuple<WTF::CrossThreadUnretainedWrapper<blink::WorkerThread>>, 0ul>(void (blink::WorkerThread::*&&)(), std::Cr::tuple<WTF::CrossThreadUnretainedWrapper<blink::WorkerThread>>&&, std::Cr::integer_sequence<unsigned long, 0ul>) + 72
20 libblink_core.dylib 0x00000001e08570e7 base::internal::Invoker<base::internal::BindState<void (blink::WorkerThread::*)(), WTF::CrossThreadUnretainedWrapper<blink::WorkerThread>>, void ()>::RunOnce(base::internal::BindStateBase*) + 55
21 libbase.dylib 0x000000010d2a2887 base::OnceCallback<void ()>::Run() && + 103
22 libbase.dylib 0x000000010d504492 base::TaskAnnotator::RunTaskImpl(base::PendingTask&) + 418
23 libbase.dylib 0x000000010d56feae _ZN4base13TaskAnnotator7RunTaskIJZNS_16sequence_manager8internal35ThreadControllerWithMessagePumpImpl10DoWorkImplEPNS_7LazyNowEE3$_0EEEvN8perfetto12StaticStringERNS_11PendingTaskEDpOT_ + 126
24 libbase.dylib 0x000000010d56f9fa base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(base::LazyNow*) + 2362
25 libbase.dylib 0x000000010d56ebb6 base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() + 246
26 libbase.dylib 0x000000010d56fd13 non-virtual thunk to base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() + 35
27 libbase.dylib 0x000000010d389497 base::MessagePumpDefault::Run(base::MessagePump::Delegate*) + 151
28 libbase.dylib 0x000000010d570661 base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool, base::TimeDelta) + 705
29 libbase.dylib 0x000000010d46b483 base::RunLoop::Run(base::Location const&) + 755
30 libblink_platform.dylib 0x00000001f0ab9b88 blink::scheduler::NonMainThreadImpl::SimpleThreadImpl::Run() + 568
31 libbase.dylib 0x000000010d5fcf0a base::SimpleThread::ThreadMain() + 74
32 libbase.dylib 0x000000010d68b2f2 base::(anonymous namespace)::ThreadFunc(void*) + 226
33 libsystem_pthread.dylib 0x00007ff81a49b4e1 _pthread_start + 125
34 libsystem_pthread.dylib 0x00007ff81a496f6b thread_start + 15
Chromium debugging resources
I built Chromium on Mac like this:
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH="$PATH:"`pwd`
cd ~/ && mkdir chromium && cd chromium
caffeinate fetch --no-history chromium
caffeinate autoninja -C out/Default chrome
./out/Default/Chromium.app/Contents/MacOS/Chromium --enable-logging --v=1
Then, I created a new empty xcode project and used the Debug > Attach to > Chromium
from the top level menu. Finally, I paused the process and set a breakpoint on the error page handler like this:
(lldb) b SadTab
It didn't yield much information so I looked for scraps of information and set further breakpoints:
- break on all exceptions – breakpoint wasn't triggered
GetTerminationStatus
– breakpoint wasn't triggeredV8_Fatal
– breakpoint wasn't triggeredPerformShutdownOnWorkerThread
– breakpoint wasn't triggered
See more information at:
- Building Chromium on Mac
- Debugging Chromium on Mac
- Enable Chromium logging
- Decoding Crash Dumps
- Crash reports on Mac
- Using minidump-stackwalk
- https://bugs.chromium.org/p/chromium/issues/detail?id=82172
- https://bugs.chromium.org/p/chromium/issues/detail?id=304846#c14
- https://chromium.googlesource.com/crashpad/crashpad/+/HEAD/handler/crashpad_handler.md