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:
+10
-2
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user