[Webkit-unassigned] [Bug 289686] New: WebAssembly worker spin loop after `worker.terminate()` or page reload

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Thu Mar 13 02:48:06 PDT 2025


https://bugs.webkit.org/show_bug.cgi?id=289686

            Bug ID: 289686
           Summary: WebAssembly worker spin loop after
                    `worker.terminate()` or page reload
           Product: WebKit
           Version: Safari 18
          Hardware: Mac (Apple Silicon)
                OS: macOS 15
            Status: NEW
          Severity: Normal
          Priority: P2
         Component: New Bugs
          Assignee: webkit-unassigned at lists.webkit.org
          Reporter: laurmaedje at gmail.com

Created attachment 474546

  --> https://bugs.webkit.org/attachment.cgi?id=474546&action=review

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.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20250313/a3061110/attachment-0001.htm>


More information about the webkit-unassigned mailing list