linebender / druid

A data-first Rust-native UI design toolkit.
https://linebender.org/druid/
Apache License 2.0
9.53k stars 569 forks source link

Windows + CPAL + SHOW_SAVE_PANEL = lockup #1021

Open jneem opened 4 years ago

jneem commented 4 years ago

On windows, if I initialize an audio device using cpal then any subsequent attempts to SHOW_SAVE_PANEL lock up my program. I have a branch in which I've modified the open_save example to demonstrate this behavior.

This was observed on the Windows 10 evaluation version available here, running in virtualbox.

jneem commented 4 years ago

Upon further investigation, this also happens when using gstreamer to play audio (however, with gstreamer it isn't triggered just by initializing gstreamer; I need to actually create an audio pipeline).

I've done a little more investigation (with cpal because it's simpler). The druid main thread blocks on IModalWindow::Show, which eventually results in a call to NtWaitForMultipleObjects. There are tons of threads blocked on NtWaitForWorkViaWorkerFactory, and then one thread blocked on GetMessageExA (which eventually also leads to NtWaitForMultipleObjects) and another thread blocked on NtUserCallHwndParamLockSafe that has things like DialogBoxIndirectParamW in its call stack.

I'm pretty clueless at this point, but maybe tomorrow I'll try to see if #1068 is relevant.

jneem commented 4 years ago

I managed to fix the lockup by doing all audio-related stuff on a separate thread. In gstreamer, it seems that I need to create the audio pipeline on a different thread; in cpal, I need to initialize the audio device on a separate thread. Maybe this is just something you have to do on windows? I couldn't find anything about it anywhere :shrug:

Zarenor commented 4 years ago

This definitely sounds a little odd to me, but if the audio lib is expecting to own the event pump for the thread (and go into an event-handling mode), that could cause this, because Druid runs on OS event loops - we don't roll our own and then pull from a separate message queue. That is, when our event-update-layout-paint cycle ends, we yield back to the OS, which is free to call back in with an event at it's leisure (or to choose not to).

I'm not familiar enough with how the audio side of things works here to know if there could be some fix we could make easily in Druid for this to behave better... The thing that definitely seems strange to me is the modal window causing a freeze. Can you close the modal, or does it freeze so that you can't?