]> git.ipfire.org Git - thirdparty/shairport-sync.git/commit
Fixed race condition when stopping other threads with SIGUSR1 612/head
authorBelbo <belbo@gmx.de>
Tue, 15 Aug 2017 20:00:57 +0000 (22:00 +0200)
committerBelbo <belbo@gmx.de>
Wed, 1 Nov 2017 19:46:05 +0000 (20:46 +0100)
commitb98e6a9ac0fa8f77d46a5cc656db388210f27659
treeebdba3cd0912f8d78e26214a949ba5c7d085a999
parent183c6f08e08688f11ced8f07ac10710275441af0
Fixed race condition when stopping other threads with SIGUSR1

Many threads have a main loop that checks some exit variable in the loop condition. To stop a thread, another thread sets that exit variable, sends a SIGUSR1 to that thread to get it out of blocking calls like read(), write() or select(), and finally joins it.

There was a race condition though: if the signal arrived after the loop condition was checked but before the blocking system function was entered, the target thread essentially ignored the signal, made the blocking call anyway, and could get stuck forever there.

The only way around this race condition is to block SIGUSR1 in the destination thread during the critical time interval. This requires that the blocking system call and the call to unblock SIGUSR1 be an atomic unit. There is only one system call that makes this possible: pselect(), which takes a signal mask to replace the current signal mask with, but only while pselect() runs. Other functions like read(), recv(), write() and sendto() may only be called if we can be sure that they don't block. For this purpose, the file descriptors must be set to non-blocking mode and we must prepend the call to them with a call to pselect() to block until the socket becomes readable/writable.
common.c
common.h
mdns_external.c
player.c
rtp.c
rtsp.c
shairport.c