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:
parent
83dee8e4e5
commit
75c289aab9
3 changed files with 26 additions and 3 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue