Pass along SIGHUP and SIGTERM from parent to child.

This commit is contained in:
Todd C. Miller
2009-10-31 17:14:52 +00:00
parent e6567f46b6
commit 94370b319f

View File

@@ -96,6 +96,8 @@ static sig_atomic_t alive = 1;
static sig_atomic_t suspended = 0; static sig_atomic_t suspended = 0;
static sig_atomic_t foreground = 0; static sig_atomic_t foreground = 0;
static sigset_t ttyblock;
static pid_t parent, child; static pid_t parent, child;
static int child_status; static int child_status;
@@ -104,9 +106,11 @@ static char slavename[PATH_MAX];
static void script_child __P((char *path, char *argv[], int, int)); static void script_child __P((char *path, char *argv[], int, int));
static void script_run __P((char *path, char *argv[], int)); static void script_run __P((char *path, char *argv[], int));
static void sync_winsize __P((int src, int dst)); static void sync_winsize __P((int src, int dst));
static void handler __P((int s));
static void sigchild __P((int s)); static void sigchild __P((int s));
static void sigcont __P((int s)); static void sigcont __P((int s));
static void sigfgbg __P((int s)); static void sigfgbg __P((int s));
static void sigrelay __P((int s));
static void sigtstp __P((int s)); static void sigtstp __P((int s));
static void sigwinch __P((int s)); static void sigwinch __P((int s));
static void flush_output __P((struct script_buf *output, struct timeval *then, static void flush_output __P((struct script_buf *output, struct timeval *then,
@@ -324,6 +328,9 @@ log_output(buf, n, then, now, ofile, tfile)
#endif #endif
{ {
struct timeval tv; struct timeval tv;
sigset_t omask;
sigprocmask(SIG_BLOCK, &ttyblock, &omask);
#ifdef HAVE_ZLIB #ifdef HAVE_ZLIB
gzwrite(ofile, buf, n); gzwrite(ofile, buf, n);
@@ -340,6 +347,8 @@ log_output(buf, n, then, now, ofile, tfile)
#endif #endif
then->tv_sec = now->tv_sec; then->tv_sec = now->tv_sec;
then->tv_usec = now->tv_usec; then->tv_usec = now->tv_usec;
sigprocmask(SIG_SETMASK, &omask, NULL);
} }
/* /*
@@ -390,7 +399,15 @@ script_execv(path, argv)
parent = getpid(); /* so child can pass signals back to us */ parent = getpid(); /* so child can pass signals back to us */
foreground = tcgetpgrp(script_fds[SFD_USERTTY]) == parent; foreground = tcgetpgrp(script_fds[SFD_USERTTY]) == parent;
/* Setup signal handlers window size changes and child exit */ /* So we can block tty-generated signals */
sigemptyset(&ttyblock);
sigaddset(&ttyblock, SIGINT);
sigaddset(&ttyblock, SIGQUIT);
sigaddset(&ttyblock, SIGTSTP);
sigaddset(&ttyblock, SIGTTIN);
sigaddset(&ttyblock, SIGTTOU);
/* Setup signal handlers window size changes and child stop/exit */
zero_bytes(&sa, sizeof(sa)); zero_bytes(&sa, sizeof(sa));
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART; sa.sa_flags = SA_RESTART;
@@ -403,7 +420,15 @@ script_execv(path, argv)
sa.sa_handler = sigcont; sa.sa_handler = sigcont;
sigaction(SIGCONT, &sa, NULL); sigaction(SIGCONT, &sa, NULL);
/* Handler for tty stop signals */ /* Relay SIG{HUP,TERM} from parent to child. */
sa.sa_handler = sigrelay;
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
/* Handler for tty-based signals */
sa.sa_flags = 0; /* do not restart syscalls for these three */
sa.sa_handler = sigtstp; sa.sa_handler = sigtstp;
sigaction(SIGTSTP, &sa, NULL); sigaction(SIGTSTP, &sa, NULL);
sigaction(SIGTTIN, &sa, NULL); sigaction(SIGTTIN, &sa, NULL);
@@ -687,6 +712,14 @@ script_child(path, argv, foreground, rbac_enabled)
sigaction(SIGTTOU, &sa, NULL); sigaction(SIGTTOU, &sa, NULL);
sigaction(SIGWINCH, &sa, NULL); sigaction(SIGWINCH, &sa, NULL);
/*
* Parent may sent signals that we need to pass on.
*/
sa.sa_flags = 0; /* do not restart syscalls for these signals. */
sa.sa_handler = handler;
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
/* Parent sends child SIGUSR1 to put command in the foreground. */ /* Parent sends child SIGUSR1 to put command in the foreground. */
sa.sa_handler = sigfgbg; sa.sa_handler = sigfgbg;
sigaction(SIGUSR1, &sa, NULL); sigaction(SIGUSR1, &sa, NULL);
@@ -749,8 +782,11 @@ script_child(path, argv, foreground, rbac_enabled)
warning("tcsetpgrp"); warning("tcsetpgrp");
} }
/* Wait for signal from child or for child to exit. */ /* Wait for signal to arrive or for child to exit. */
for (;;) { for (;;) {
if (suspended == SIGHUP || suspended == SIGTERM)
killpg(child, suspended);
pid = waitpid(child, &status, WUNTRACED); pid = waitpid(child, &status, WUNTRACED);
if (pid != child) { if (pid != child) {
if (pid == -1 && errno == EINTR) if (pid == -1 && errno == EINTR)
@@ -941,6 +977,30 @@ sigchild(s)
errno = serrno; errno = serrno;
} }
/*
* Generic handler for signals passed from parent -> child
*/
static void
handler(s)
int s;
{
suspended = s;
}
/*
* Handler for SIG{HUP,TERM} in parent, relays to child.
*/
static void
sigrelay(s)
int s;
{
int serrno = errno;
kill(child, s);
errno = serrno;
}
/* /*
* Signal handler for SIG{TSTP,TTOU,TTIN} * Signal handler for SIG{TSTP,TTOU,TTIN}
*/ */