mirror of
https://github.com/libsdl-org/SDL
synced 2024-11-20 16:06:10 -07:00
pipewire: i/o callbacks should avoid higher-level iteration during device open.
Sometimes these callbacks will fire while we're still waiting on state to settle down in PIPEWIRE_OpenDevice, which means we're holding the device lock, but then the i/o callback will fire from a background thread and also try to grab the device lock, but can't, because PIPEWIRE_OpenDevice is holding it and waiting for this i/o callback to finish...hence, a deadlock. So now, if the device is still opening, output callbacks will write silence and input callbacks will just flush the buffer, without calling the main iterate function, and thus avoid obtaining the lock.
This commit is contained in:
parent
119b4fa5f5
commit
32cc92dceb
1 changed files with 25 additions and 2 deletions
|
@ -939,7 +939,21 @@ static bool PIPEWIRE_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, in
|
|||
|
||||
static void output_callback(void *data)
|
||||
{
|
||||
SDL_PlaybackAudioThreadIterate((SDL_AudioDevice *)data);
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) data;
|
||||
|
||||
// this callback can fire in a background thread during OpenDevice, while we're still blocking
|
||||
// _with the device lock_ until the stream is ready, causing a deadlock. Write silence in this case.
|
||||
if (device->hidden->stream_init_status != PW_READY_FLAG_ALL_BITS) {
|
||||
int bufsize = 0;
|
||||
Uint8 *buf = PIPEWIRE_GetDeviceBuf(device, &bufsize);
|
||||
if (buf && bufsize) {
|
||||
SDL_memset(buf, device->silence_value, bufsize);
|
||||
}
|
||||
PIPEWIRE_PlayDevice(device, buf, bufsize);
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_PlaybackAudioThreadIterate(device);
|
||||
}
|
||||
|
||||
static void PIPEWIRE_FlushRecording(SDL_AudioDevice *device)
|
||||
|
@ -980,7 +994,16 @@ static int PIPEWIRE_RecordDevice(SDL_AudioDevice *device, void *buffer, int bufl
|
|||
|
||||
static void input_callback(void *data)
|
||||
{
|
||||
SDL_RecordingAudioThreadIterate((SDL_AudioDevice *)data);
|
||||
SDL_AudioDevice *device = (SDL_AudioDevice *) data;
|
||||
|
||||
// this callback can fire in a background thread during OpenDevice, while we're still blocking
|
||||
// _with the device lock_ until the stream is ready, causing a deadlock. Drop data in this case.
|
||||
if (device->hidden->stream_init_status != PW_READY_FLAG_ALL_BITS) {
|
||||
PIPEWIRE_FlushRecording(device);
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_RecordingAudioThreadIterate(device);
|
||||
}
|
||||
|
||||
static void stream_add_buffer_callback(void *data, struct pw_buffer *buffer)
|
||||
|
|
Loading…
Reference in a new issue