WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
NEW
289686
WebAssembly worker spin loop after `worker.terminate()` or page reload
https://bugs.webkit.org/show_bug.cgi?id=289686
Summary
WebAssembly worker spin loop after `worker.terminate()` or page reload
Laurenz Mädje
Reported
2025-03-13 02:48:06 PDT
Created
attachment 474546
[details]
A minimal reproduction of the bug. Calling `worker.terminate()` or reloading the page when there's a web worker that runs non-yielding WebAssembly does not properly terminate it. The WebAssembly continues running until the tab is fully closed. Moreover, atomic operations stop working correctly, which may cause workers relying on atomic operations for correct operation (e.g. a mutex implementation) to go into a spin loop, consuming tons of CPU and battery. I've attached a complete minimal reproduction as a ZIP file. It can also be found here:
https://github.com/laurmaedje/safari-worker-bug
The reproduction page starts a web worker, which loads WebAssembly with shared memory, and runs an export from the WebAssembly. This export never yields back to the event loop. Rather, it goes into a loop where it `memory.atomic.wait32`s for a memory location to change (which never changes). During normal worker operation, this wait simply suspends and does not cause any CPU usage. However, as soon as the worker is killed via `worker.terminate()`, CPU usage goes all the way to 100%. I can't say for sure what happens, but my best guess is that `worker.terminate()` doesn't correctly shut down the non-yielding WebAssembly, but _does_ release enough resources for the memory wait operation to not work correctly anymore, making it return immediately instead, effectively making the WASM go into a spin loop. In my view, the bug here is two-layered: The fact that the atomic instruction does not work correctly anymore is the symptom that causes high CPU usage, but the core problem is that neither `worker.terminate()` nor a page reload are able to kill a non-yielding WebAssembly function.
Attachments
A minimal reproduction of the bug.
(46.41 KB, application/zip)
2025-03-13 02:48 PDT
,
Laurenz Mädje
no flags
Details
View All
Add attachment
proposed patch, testcase, etc.
Laurenz Mädje
Comment 1
2025-03-13 12:12:37 PDT
I tested in Safari Technology Preview and the atomics spin loop appears to be fixed! Probably by
https://github.com/WebKit/WebKit/commit/5b0655d476fe2a67bbee13c722a08bd0393cc063
(at least the diff looks very plausible), which fixed
https://bugs.webkit.org/show_bug.cgi?id=281657#c1
. What still remains though is the fact that a WebAssembly function that actively spins prevents a worker from being terminated by `worker.terminate()`.
Radar WebKit Bug Importer
Comment 2
2025-03-20 02:49:17 PDT
<
rdar://problem/147482360
>
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug