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
This commit is contained in:
Rom Lemarchand 2013-01-09 10:20:25 -08:00 committed by Android (Google) Code Review
parent 83dee8e4e5
commit 75c289aab9
3 changed files with 26 additions and 3 deletions

View file

@ -18,6 +18,8 @@
#ifndef __LIBS_LOGWRAP_H
#define __LIBS_LOGWRAP_H
#include <stdbool.h>
__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

View file

@ -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);

View file

@ -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);