From 75c289aab9b81dc2235680cf141a4b183ee49391 Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Wed, 9 Jan 2013 10:20:25 -0800 Subject: logwrap: wait for child process when receiving SIGINT or SIGQUIT - Wait for the child to exit before propagating SIGINT and SIGQUIT to the parent - Add ignore_int_quit argument to logwrap() that gives the caller the option to ignore SIGINT and SIGQUIT while logwrap is running Change-Id: If5c96cf23094917211310f00aa6aed515f110f5b --- logwrapper/include/logwrap/logwrap.h | 8 +++++++- logwrapper/logwrap.c | 19 ++++++++++++++++++- logwrapper/logwrapper.c | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/logwrapper/include/logwrap/logwrap.h b/logwrapper/include/logwrap/logwrap.h index 722dda2..6593f3c 100644 --- a/logwrapper/include/logwrap/logwrap.h +++ b/logwrapper/include/logwrap/logwrap.h @@ -18,6 +18,8 @@ #ifndef __LIBS_LOGWRAP_H #define __LIBS_LOGWRAP_H +#include + __BEGIN_DECLS /* @@ -36,13 +38,17 @@ __BEGIN_DECLS * NULL-terminated * status: the equivalent child status as populated by wait(status). This * value is only valid when logwrap successfully completes + * ignore_int_quit: set to true if you want to completely ignore SIGINT and + * SIGQUIT while logwrap is running. This may force the end-user to + * send a signal twice to signal the caller (once for the child, and + * once for the caller) * * Return value: * 0 when logwrap successfully run the child process and captured its status * -1 when an internal error occurred * */ -int logwrap(int argc, char* argv[], int *status); +int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit); __END_DECLS diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c index ef457de..99a462f 100644 --- a/logwrapper/logwrap.c +++ b/logwrapper/logwrap.c @@ -176,13 +176,15 @@ void sigchld_handler(int sig) { write(signal_fd_write, &sig, 1); } -int logwrap(int argc, char* argv[], int *status) { +int logwrap(int argc, char* argv[], int *status, bool ignore_int_quit) { pid_t pid; int parent_ptty; int child_ptty; char *child_devname = NULL; struct sigaction chldact; struct sigaction oldchldact; + struct sigaction intact; + struct sigaction quitact; sigset_t blockset; sigset_t oldset; int sockets[2]; @@ -204,6 +206,8 @@ int logwrap(int argc, char* argv[], int *status) { } sigemptyset(&blockset); + sigaddset(&blockset, SIGINT); + sigaddset(&blockset, SIGQUIT); sigaddset(&blockset, SIGCHLD); sigprocmask(SIG_BLOCK, &blockset, &oldset); @@ -231,6 +235,8 @@ int logwrap(int argc, char* argv[], int *status) { fatal("This should never happen\n"); return -1; } else { + struct sigaction ignact; + memset(&chldact, 0, sizeof(chldact)); chldact.sa_handler = sigchld_handler; chldact.sa_flags = SA_NOCLDSTOP; @@ -245,6 +251,13 @@ int logwrap(int argc, char* argv[], int *status) { "handler and might cause interaction issues"); } + if (ignore_int_quit) { + memset(&ignact, 0, sizeof(ignact)); + ignact.sa_handler = SIG_IGN; + sigaction(SIGINT, &ignact, &intact); + sigaction(SIGQUIT, &ignact, &quitact); + } + rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); if (rc == -1) { char msg[40]; @@ -268,6 +281,10 @@ int logwrap(int argc, char* argv[], int *status) { close(sockets[0]); close(sockets[1]); err_socketpair: + if (ignore_int_quit) { + sigaction(SIGINT, &intact, NULL); + sigaction(SIGQUIT, &quitact, NULL); + } sigaction(SIGCHLD, &oldchldact, NULL); err_fork: sigprocmask(SIG_SETMASK, &oldset, NULL); diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c index e647b4d..563fcee 100644 --- a/logwrapper/logwrapper.c +++ b/logwrapper/logwrapper.c @@ -59,7 +59,7 @@ int main(int argc, char* argv[]) { usage(); } - rc = logwrap(argc - 1, &argv[1], &status); + rc = logwrap(argc - 1, &argv[1], &status, true); if (!rc) { if (WIFEXITED(status)) rc = WEXITSTATUS(status); -- cgit v1.1