Avoid menu deadlocks in Pulse and ALSA. (#8265)

Buggy menu code most likely, but audio backends can be defensive about
it.
This commit is contained in:
Hans-Kristian Arntzen 2019-02-12 15:31:09 +01:00 committed by bparker06
parent 2ccc6534ee
commit b3e2df53d2
2 changed files with 22 additions and 0 deletions

View File

@ -180,6 +180,7 @@ error:
#define BYTES_TO_FRAMES(bytes, frame_bits) ((bytes) * 8 / frame_bits) #define BYTES_TO_FRAMES(bytes, frame_bits) ((bytes) * 8 / frame_bits)
#define FRAMES_TO_BYTES(frames, frame_bits) ((frames) * frame_bits / 8) #define FRAMES_TO_BYTES(frames, frame_bits) ((frames) * frame_bits / 8)
static bool alsa_start(void *data, bool is_shutdown);
static ssize_t alsa_write(void *data, const void *buf_, size_t size_) static ssize_t alsa_write(void *data, const void *buf_, size_t size_)
{ {
alsa_t *alsa = (alsa_t*)data; alsa_t *alsa = (alsa_t*)data;
@ -188,6 +189,12 @@ static ssize_t alsa_write(void *data, const void *buf_, size_t size_)
snd_pcm_sframes_t size = BYTES_TO_FRAMES(size_, alsa->frame_bits); snd_pcm_sframes_t size = BYTES_TO_FRAMES(size_, alsa->frame_bits);
size_t frames_size = alsa->has_float ? sizeof(float) : sizeof(int16_t); size_t frames_size = alsa->has_float ? sizeof(float) : sizeof(int16_t);
/* Workaround buggy menu code.
* If a write happens while we're paused, we might never progress. */
if (alsa->is_paused)
if (!alsa_start(alsa, false))
return -1;
if (alsa->nonblock) if (alsa->nonblock)
{ {
while (size) while (size)
@ -269,6 +276,8 @@ static bool alsa_alive(void *data)
static bool alsa_stop(void *data) static bool alsa_stop(void *data)
{ {
alsa_t *alsa = (alsa_t*)data; alsa_t *alsa = (alsa_t*)data;
if (alsa->is_paused)
return true;
if (alsa->can_pause if (alsa->can_pause
&& !alsa->is_paused) && !alsa->is_paused)
@ -293,6 +302,8 @@ static void alsa_set_nonblock_state(void *data, bool state)
static bool alsa_start(void *data, bool is_shutdown) static bool alsa_start(void *data, bool is_shutdown)
{ {
alsa_t *alsa = (alsa_t*)data; alsa_t *alsa = (alsa_t*)data;
if (!alsa->is_paused)
return true;
if (alsa->can_pause if (alsa->can_pause
&& alsa->is_paused) && alsa->is_paused)

View File

@ -237,12 +237,19 @@ error:
return NULL; return NULL;
} }
static bool pulse_start(void *data, bool is_shutdown);
static ssize_t pulse_write(void *data, const void *buf_, size_t size) static ssize_t pulse_write(void *data, const void *buf_, size_t size)
{ {
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
const uint8_t *buf = (const uint8_t*)buf_; const uint8_t *buf = (const uint8_t*)buf_;
size_t written = 0; size_t written = 0;
/* Workaround buggy menu code.
* If a write happens while we're paused, we might never progress. */
if (pa->is_paused)
if (!pulse_start(pa, false))
return -1;
pa_threaded_mainloop_lock(pa->mainloop); pa_threaded_mainloop_lock(pa->mainloop);
while (size) while (size)
{ {
@ -270,6 +277,8 @@ static bool pulse_stop(void *data)
{ {
bool ret; bool ret;
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
if (pa->is_paused)
return true;
RARCH_LOG("[PulseAudio]: Pausing.\n"); RARCH_LOG("[PulseAudio]: Pausing.\n");
@ -296,6 +305,8 @@ static bool pulse_start(void *data, bool is_shutdown)
{ {
bool ret; bool ret;
pa_t *pa = (pa_t*)data; pa_t *pa = (pa_t*)data;
if (!pa->is_paused)
return true;
RARCH_LOG("[PulseAudio]: Unpausing.\n"); RARCH_LOG("[PulseAudio]: Unpausing.\n");