#include <sys_defs.h>
#include <signal.h>
#include <unistd.h>
#include <msg.h>
#include <posix_signals.h>
#include "master.h"
#ifdef USE_SIG_RETURN
#include <sys/syscall.h>
#endif
#ifndef USE_SIG_RETURN
#define USE_SIG_PIPE
#endif
#ifdef USE_SIG_PIPE
#include <errno.h>
#include <fcntl.h>
#include <iostuff.h>
#include <events.h>
int master_sig_pipe[2];
#define SIG_PIPE_WRITE_FD master_sig_pipe[1]
#define SIG_PIPE_READ_FD master_sig_pipe[0]
#endif
int master_gotsigchld;
int master_gotsighup;
static void master_sighup(int sig)
{
master_gotsighup = sig;
}
#ifdef USE_SIG_RETURN
static void master_sigchld(int sig, int code, struct sigcontext * scp)
{
master_gotsigchld = sig;
if (scp != NULL && scp->sc_syscall == SYS_select) {
scp->sc_syscall_action = SIG_RETURN;
#ifndef SA_RESTART
} else if (scp != NULL) {
scp->sc_syscall_action = SIG_RESTART;
#endif
}
}
#else
#ifdef USE_SIG_PIPE
static void master_sigchld(int unused_sig)
{
int saved_errno = errno;
if (write(SIG_PIPE_WRITE_FD, "", 1) != 1)
msg_warn("write to SIG_PIPE_WRITE_FD failed: %m");
errno = saved_errno;
}
static void master_sig_event(int unused_event, char *unused_context)
{
char c[1];
while (read(SIG_PIPE_READ_FD, c, 1) > 0)
;
master_gotsigchld = 1;
}
#else
static void master_sigchld(int sig)
{
master_gotsigchld = sig;
}
#endif
#endif
static void master_sigdeath(int sig)
{
char *myname = "master_sigdeath";
struct sigaction action;
pid_t pid = getpid();
msg_info("terminating on signal %d", sig);
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
action.sa_handler = SIG_IGN;
if (sigaction(SIGTERM, &action, (struct sigaction *) 0) < 0)
msg_fatal("%s: sigaction: %m", myname);
if (kill(-pid, SIGTERM) < 0)
msg_fatal("%s: kill process group: %m", myname);
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
action.sa_handler = SIG_DFL;
if (sigaction(sig, &action, (struct sigaction *) 0) < 0)
msg_fatal("%s: sigaction: %m", myname);
if (kill(pid, sig) < 0)
msg_fatal("%s: kill myself: %m", myname);
}
void master_sigsetup(void)
{
char *myname = "master_sigsetup";
struct sigaction action;
static int sigs[] = {
SIGINT, SIGQUIT, SIGILL, SIGBUS, SIGSEGV, SIGTERM,
};
unsigned i;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
action.sa_handler = master_sigdeath;
for (i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++)
if (sigaction(sigs[i], &action, (struct sigaction *) 0) < 0)
msg_fatal("%s: sigaction(%d): %m", myname, sigs[i]);
#ifdef USE_SIG_PIPE
if (pipe(master_sig_pipe))
msg_fatal("pipe: %m");
non_blocking(SIG_PIPE_WRITE_FD, NON_BLOCKING);
non_blocking(SIG_PIPE_READ_FD, NON_BLOCKING);
close_on_exec(SIG_PIPE_WRITE_FD, CLOSE_ON_EXEC);
close_on_exec(SIG_PIPE_READ_FD, CLOSE_ON_EXEC);
event_enable_read(SIG_PIPE_READ_FD, master_sig_event, (char *) 0);
#endif
#ifdef SA_RESTART
action.sa_flags |= SA_RESTART;
#endif
action.sa_handler = master_sighup;
if (sigaction(SIGHUP, &action, (struct sigaction *) 0) < 0)
msg_fatal("%s: sigaction(%d): %m", myname, SIGHUP);
action.sa_flags |= SA_NOCLDSTOP;
action.sa_handler = master_sigchld;
if (sigaction(SIGCHLD, &action, (struct sigaction *) 0) < 0)
msg_fatal("%s: sigaction(%d): %m", myname, SIGCHLD);
}