avoid recursive mutex acquisition in sndio backend

Ending a RTSP session while running on OpenBSD using sndio backend causes the
following crash:

	#0  thrkill ()
	#1  0x000005208224403e in _libc_abort
	#2  0x00000520821b77be in _rthread_mutex_trylock
	#3  _rthread_mutex_timedlock
	#4  0x0000051e0d54e2c0 in stop ()
	#5  0x0000051e0d544e85 in player_thread_cleanup_handler
	#6  0x0000052082243126 in _libc_pthread_exit
	#7  0x000005209a158700 in sigthr_handler
	#8  <signal handler called>
	#9  _thread_sys_poll ()
	#10 0x000005208223533e in _libc_poll_cancel
	#11 0x00000520df54c9a0 in sio_psleep
	#12 0x00000520df54cc1f in sio_write
	#13 0x0000051e0d54e27a in play
	#14 0x0000051e0d547fc0 in player_thread_func
	#15 0x000005209a158cc1 in _rthread_start
	#16 0x000005208223565a in __tfork_thread

The player thread is blocking inside sio_write() -> poll(2) while the thread is
being terminated. The stop routine tied to the same backend is invoked through
player_thread_cleanup_handler() which tries to acquire the mutex which it
already acquired before invoking sio_write(). Avoiding blocking writes would
require switching to async I/O which is quite an undertaking.

The fact that there's only one `struct sio_hdl *' instance in the compilation
unit sort of implies there can only be one player thread at a time. Therefore
fix the crash by only trying to acquire the mutex and continue as usual if it's
already acquired.
This commit is contained in:
Anton Lindqvist
2021-12-05 09:08:01 +01:00
parent a05db62100
commit 57af5f3c10
+10 -2
View File
@@ -239,11 +239,19 @@ static int play(void *buf, int frames) {
}
static void stop() {
pthread_mutex_lock(&sndio_mutex);
int gotlock = 1;
// The player thread could already be waiting in sio_write() during
// termination implying that the same thread already have acquired the mutex.
if (pthread_mutex_trylock(&sndio_mutex))
gotlock = 0;
if (!sio_stop(hdl))
die("sndio: unable to stop");
written = played = 0;
pthread_mutex_unlock(&sndio_mutex);
if (gotlock)
pthread_mutex_unlock(&sndio_mutex);
}
static void onmove_cb(__attribute__((unused)) void *arg, int delta) {