emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.88k stars 3.32k forks source link

Deadlock with -sPROXY_TO_PTHREAD and _emscripten_set_resize_callback_on_thread #22442

Closed stbergmann closed 3 weeks ago

stbergmann commented 3 months ago

As mentioned in the mail thread at https://groups.google.com/g/emscripten-discuss/c/Nnr0ENExjoE "_emscripten_run_callback_on_thread causing deadlocks": After switching from emsdk 3.1.46 to recent Emscripten trunk (emcc -v: emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.65-git (23197a2d369b8e47e7ea1ba7c498309da835b718)), my application started to deadlock on start. The application is recent LibreOffice trunk (see https://git.libreoffice.org/core/+/refs/heads/master/static/README.wasm.md), using -sPROXY_TO_PTHREAD on top of a slightly modified Qt5 (to make that support -sPROXY_TO_PTHREAD).

The browser's main thread is still serving an earlier asynchronous request sent from the application's main pthread via emscripten_async_run_in_main_runtime_thread,

a_cas_p (soffice.wasm:0x8139063)
futex_wait_main_browser_thread (soffice.wasm:0x8138f94)
emscripten_futex_wait (emscripten_futex_wait.c:130)
__timedwait_cp (__timedwait.c:94)
__pthread_cond_timedwait (pthread_cond_timedwait.c:117)
pthread_cond_wait (pthread_cond_wait.c:5)
emscripten_proxy_sync_with_ctx (proxying.c:385)
emscripten_proxy_sync (proxying.c:405)
_emscripten_run_callback_on_thread (callback.c:39)
(anonymous) (VM9:1236)
focusEventHandlerFunc (VM9:14188)
eventHandler.eventListenerFunc (VM9:11156)
methodCaller<() => void> (VM54:4)
__emval_call_method (VM9:9810)
void emscripten::val::call<void>(char const*) const::'lambda'(emscripten::internal::_EM_METHOD_CALLER*, emscripten::_EM_VAL*, emscripten::internal::_EM_DESTRUCTORS**, void const*)::operator()(emscripten::internal::_EM_METHOD_CALLER*, emscripten::_EM_VAL*, emscripten::internal::_EM_DESTRUCTORS**, void const*) const (val.h:532)
void emscripten::val::internalCall<(emscripten::internal::EM_METHOD_CALLER_KIND)0, void, void emscripten::val::call<void>(char const*) const::'lambda'(emscripten::internal::_EM_METHOD_CALLER*, emscripten::_EM_VAL*, emscripten::internal::_EM_DESTRUCTORS**, void const*)>(void emscripten::val::call<void>(char const*) const::'lambda'(emscripten::internal::_EM_METHOD_CALLER*, emscripten::_EM_VAL*, emscripten::internal::_EM_DESTRUCTORS**, void const*)) const (val.h:658)
$setFocus() (soffice.wasm:0x8117c51)
_do_call (proxying_legacy.c:174)
em_task_queue_execute (em_task_queue.c:176)
receive_notification (em_task_queue.c:218)
em_task_queue_execute (em_task_queue.c:176)
_emscripten_check_mailbox (thread_mailbox.c:83)
(anonymous) (VM9:1236)
callUserCallback (VM9:9634)
checkMailbox (VM9:9669)
Promise.then
__emscripten_thread_mailbox_await (VM9:9651)
checkMailbox (VM9:9668)
Promise.then
__emscripten_thread_mailbox_await (VM9:9651)
checkMailbox (VM9:9668)
[...]

and blocks on a synchronous call into the application's main pthread, while the application's main pthread is blocked in a call to _emscripten_set_resize_callback_on_thread,

emscripten_futex_wait (emscripten_futex_wait.c:155)
__timedwait_cp (__timedwait.c:94)
__pthread_cond_timedwait (pthread_cond_timedwait.c:117)
pthread_cond_wait (pthread_cond_wait.c:5)
emscripten_proxy_sync_with_ctx (proxying.c:385)
emscripten_proxy_sync (proxying.c:405)
_emscripten_run_on_main_thread_js (proxying.c:624)
(anonymous) (da84c39f-b498-43f4-9f35-01795880a0ba:1236)
proxyToMainThread (da84c39f-b498-43f4-9f35-01795880a0ba:1677)
_emscripten_set_resize_callback_on_thread (da84c39f-b498-43f4-9f35-01795880a0ba:14417)
$QWasmIntegration::QWasmIntegration() (soffice.wasm:0x8112b69)
$QWasmIntegrationPlugin::create(QString const&, QStringList const&) (soffice.wasm:0x810d693)
$QPlatformIntegrationPlugin::create(QString const&, QStringList const&, int&, char**) (soffice.wasm:0x7def4c9)
[...]

The deadlock goes away if I either revert https://github.com/emscripten-core/emscripten/commit/c41f6590b1f9fcda12b2adb2d32cd352f163e717 "Remove use of legacy proxy API from library_html5.js. NFC (#20370)" or fix that commit with

diff --git a/system/lib/html5/callback.c b/system/lib/html5/callback.c
index 1bec1ea78..541e5ec20 100644
--- a/system/lib/html5/callback.c
+++ b/system/lib/html5/callback.c
@@ -36,7 +36,7 @@ void _emscripten_run_callback_on_thread(pthread_t t,
     .user_data = user_data,
   };

-  if (!emscripten_proxy_sync(q, t, do_callback, &arg)) {
-    assert(false && "emscripten_proxy_sync failed");
+  if (!emscripten_proxy_async(q, t, do_callback, &arg)) {
+    assert(false && "emscripten_proxy_async failed");
   }
 }
stbergmann commented 3 months ago

[...]

or fix that commit with

see https://github.com/emscripten-core/emscripten/pull/22443 "Make _emscripten_run_callback_on_thread asynchronous"