From de9d5941b84bb36e54f1bb57416604f7e87c462e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net> Date: Fri, 19 Mar 2021 13:54:35 -0400 Subject: [PATCH] Fix race condition when handle is opened by playing a sample. Caused a SyncTERM hang if it played a FG beep. --- src/xpdev/xpbeep.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/xpdev/xpbeep.c b/src/xpdev/xpbeep.c index 9693f7ba97..d1059f1ada 100644 --- a/src/xpdev/xpbeep.c +++ b/src/xpdev/xpbeep.c @@ -212,6 +212,7 @@ struct alsa_api_struct *alsa_api=NULL; #ifdef XPDEV_THREAD_SAFE static void init_sample(void); +static BOOL xp_play_sample_locked(const unsigned char *sample, size_t size, BOOL background); #endif /********************************************************************************/ @@ -418,10 +419,12 @@ DLLCALL xptone_open_locked(void) handle_rc++; #ifdef XPDEV_THREAD_SAFE pthread_mutex_unlock(&handle_mutex); -#endif + pthread_mutex_lock(&sample_mutex); + if (samples_posted == 0) + xp_play_sample_locked((unsigned char *)"\x80", 1, FALSE); + pthread_mutex_unlock(&sample_mutex); +#else xptone(0, 1, WAVE_SHAPE_SQUARE); -#ifdef XPDEV_THREAD_SAFE - pthread_mutex_lock(&handle_mutex); #endif if (pulseaudio_device_open_failed) { handle_type = SOUND_DEVICE_CLOSED; @@ -995,20 +998,20 @@ void DLLCALL xp_play_sample_thread(void *data) waited=FALSE; posted_last=FALSE; pthread_mutex_lock(&handle_mutex); - if(pthread_mutex_lock(&sample_mutex)!=0) { - pthread_mutex_unlock(&handle_mutex); - goto error_return; - } if(handle_type==SOUND_DEVICE_CLOSED) { must_close=TRUE; if(!xptone_open_locked()) { sem_post(&sample_complete_sem); - pthread_mutex_unlock(&sample_mutex); pthread_mutex_unlock(&handle_mutex); continue; } } + + if(pthread_mutex_lock(&sample_mutex)!=0) { + pthread_mutex_unlock(&handle_mutex); + goto error_return; + } this_sample_size=sample_size; FREE_AND_NULL(sample); sample=(unsigned char *)malloc(sample_size); @@ -1067,15 +1070,8 @@ init_sample(void) sem_init(&sample_complete_sem, 0, 0); } -/* - * This MUST not return false after sample goes into the sample buffer in the background. - * If it does, the caller won't be able to free() it. - */ -BOOL DLLCALL xp_play_sample(const unsigned char *sample, size_t size, BOOL background) +static BOOL xp_play_sample_locked(const unsigned char *sample, size_t size, BOOL background) { - pthread_once(&sample_initialized_pto, init_sample); - - pthread_mutex_lock(&sample_mutex); if(!sample_thread_running) { _beginthread(xp_play_sample_thread, 0,NULL); sem_wait(&sample_complete_sem); @@ -1099,8 +1095,22 @@ BOOL DLLCALL xp_play_sample(const unsigned char *sample, size_t size, BOOL backg samples_posted--; } } + return TRUE; +} + +/* + * This MUST not return false after sample goes into the sample buffer in the background. + * If it does, the caller won't be able to free() it. + */ +BOOL DLLCALL xp_play_sample(const unsigned char *sample, size_t size, BOOL background) +{ + BOOL ret; + pthread_once(&sample_initialized_pto, init_sample); + + pthread_mutex_lock(&sample_mutex); + ret = xp_play_sample_locked(sample, size, background); pthread_mutex_unlock(&sample_mutex); - return(TRUE); + return(ret); } #else BOOL DLLCALL xp_play_sample(const unsigned char *sample, size_t sample_size, BOOL background) -- GitLab