mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-21 17:21:44 +00:00
pipewire: Fix possible deadlock when opening a device
If the pipewire thread invokes output_callback() while we're still waiting inside PIPEWIRE_OpenDevice(), we will deadlock. The pipewire thread owns the loop lock and is blocked on the audio device lock, which cannot be released because pw_thread_loop_wait() needs to reacquire the loop lock before it can return and allow PIPEWIRE_OpenDevice() to complete and release the device lock.
This commit is contained in:

committed by
Sam Lantinga

parent
70f657e520
commit
945da099ae
@@ -44,7 +44,9 @@ enum PW_READY_FLAGS
|
|||||||
{
|
{
|
||||||
PW_READY_FLAG_BUFFER_ADDED = 0x1,
|
PW_READY_FLAG_BUFFER_ADDED = 0x1,
|
||||||
PW_READY_FLAG_STREAM_READY = 0x2,
|
PW_READY_FLAG_STREAM_READY = 0x2,
|
||||||
PW_READY_FLAG_ALL_BITS = 0x3
|
PW_READY_FLAG_ALL_PREOPEN_BITS = 0x3,
|
||||||
|
PW_READY_FLAG_OPEN_COMPLETE = 0x4,
|
||||||
|
PW_READY_FLAG_ALL_BITS = 0x7
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PW_ID_TO_HANDLE(x) (void *)((uintptr_t)x)
|
#define PW_ID_TO_HANDLE(x) (void *)((uintptr_t)x)
|
||||||
@@ -1215,12 +1217,13 @@ static bool PIPEWIRE_OpenDevice(SDL_AudioDevice *device)
|
|||||||
return SDL_SetError("Pipewire: Failed to start stream loop");
|
return SDL_SetError("Pipewire: Failed to start stream loop");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait until all init flags are set or the stream has failed.
|
// Wait until all pre-open init flags are set or the stream has failed.
|
||||||
PIPEWIRE_pw_thread_loop_lock(priv->loop);
|
PIPEWIRE_pw_thread_loop_lock(priv->loop);
|
||||||
while (priv->stream_init_status != PW_READY_FLAG_ALL_BITS &&
|
while (priv->stream_init_status != PW_READY_FLAG_ALL_PREOPEN_BITS &&
|
||||||
PIPEWIRE_pw_stream_get_state(priv->stream, NULL) != PW_STREAM_STATE_ERROR) {
|
PIPEWIRE_pw_stream_get_state(priv->stream, NULL) != PW_STREAM_STATE_ERROR) {
|
||||||
PIPEWIRE_pw_thread_loop_wait(priv->loop);
|
PIPEWIRE_pw_thread_loop_wait(priv->loop);
|
||||||
}
|
}
|
||||||
|
priv->stream_init_status |= PW_READY_FLAG_OPEN_COMPLETE;
|
||||||
PIPEWIRE_pw_thread_loop_unlock(priv->loop);
|
PIPEWIRE_pw_thread_loop_unlock(priv->loop);
|
||||||
|
|
||||||
if (PIPEWIRE_pw_stream_get_state(priv->stream, &error) == PW_STREAM_STATE_ERROR) {
|
if (PIPEWIRE_pw_stream_get_state(priv->stream, &error) == PW_STREAM_STATE_ERROR) {
|
||||||
|
Reference in New Issue
Block a user