event/SignalMonitor: unblock signals after fork

Fixes hanging child process in the "pipe" output plugin.
This commit is contained in:
Max Kellermann 2014-02-18 19:13:50 +01:00
parent 7fee85c80a
commit 5e1e92626c
2 changed files with 24 additions and 1 deletions

2
NEWS
View File

@ -3,6 +3,8 @@ ver 0.18.9 (not yet released)
- vorbis: fix linker failure when libvorbis/libogg are static - vorbis: fix linker failure when libvorbis/libogg are static
* encoder * encoder
- vorbis: fix another linker failure - vorbis: fix another linker failure
* output
- pipe: fix hanging child process due to blocked signals
ver 0.18.8 (2014/02/07) ver 0.18.8 (2014/02/07)
* decoder * decoder

View File

@ -39,6 +39,10 @@
#include <algorithm> #include <algorithm>
#ifdef USE_SIGNALFD
#include <pthread.h>
#endif
class SignalMonitor final : private SocketMonitor { class SignalMonitor final : private SocketMonitor {
#ifdef USE_SIGNALFD #ifdef USE_SIGNALFD
SignalFD fd; SignalFD fd;
@ -99,7 +103,21 @@ static std::atomic_bool signal_pending[MAX_SIGNAL];
static Manual<SignalMonitor> monitor; static Manual<SignalMonitor> monitor;
#ifndef USE_SIGNALFD #ifdef USE_SIGNALFD
/**
* This is a pthread_atfork() callback that unblocks the signals that
* were blocked for our signalfd(). Without this, our child processes
* would inherit the blocked signals.
*/
static void
at_fork_child()
{
sigprocmask(SIG_UNBLOCK, &signal_mask, nullptr);
}
#else
static void static void
SignalCallback(int signo) SignalCallback(int signo)
{ {
@ -108,6 +126,7 @@ SignalCallback(int signo)
if (!signal_pending[signo].exchange(true)) if (!signal_pending[signo].exchange(true))
monitor->WakeUp(); monitor->WakeUp();
} }
#endif #endif
void void
@ -115,6 +134,8 @@ SignalMonitorInit(EventLoop &loop)
{ {
#ifdef USE_SIGNALFD #ifdef USE_SIGNALFD
sigemptyset(&signal_mask); sigemptyset(&signal_mask);
pthread_atfork(nullptr, nullptr, at_fork_child);
#endif #endif
monitor.Construct(loop); monitor.Construct(loop);