diff options
author | Paul Mackerras <paulus@samba.org> | 2006-06-04 03:52:50 +0000 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-06-04 03:52:50 +0000 |
commit | d929a8d4e1d3e5ff15068ea3b538598b6d448943 (patch) | |
tree | ff466db52863adccc6e2f8815a2664b616b3cb4c /pppd/main.c | |
parent | d6e4ac0c098b02de9cc7907133d209da1bbf99df (diff) | |
download | ppp-d929a8d4e1d3e5ff15068ea3b538598b6d448943.tar.gz |
Fix snafu in run_program(). Patch from Robert Vogelgesang.
This patch splits out the major part of reap_kids() into a new
function, forget_child(), and calls this new function instead of
reap_kids() in run_program(), after having waitpid()'ed for a child.
Rationale:
The waitpid() at the start of reap_kids() has no chance to get the
PID of the child already waited for in run_program().
As a consequence, the PID of that child will stay in the list of all
children until the end of the pppd process, which is bad, because
pppd will then try to kill -TERM that PID (and might kill some
innocent third party at this point).
Diffstat (limited to 'pppd/main.c')
-rw-r--r-- | pppd/main.c | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/pppd/main.c b/pppd/main.c index fe34cff..9c4cb46 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -66,7 +66,7 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define RCSID "$Id: main.c,v 1.152 2005/08/25 23:59:34 paulus Exp $" +#define RCSID "$Id: main.c,v 1.153 2006/06/04 03:52:50 paulus Exp $" #include <stdio.h> #include <ctype.h> @@ -242,6 +242,7 @@ static void toggle_debug __P((int)); static void open_ccp __P((int)); static void bad_signal __P((int)); static void holdoff_end __P((void *)); +static void forget_child __P((int pid, int status)); static int reap_kids __P((void)); static void childwait_end __P((void *)); @@ -1711,7 +1712,7 @@ run_program(prog, args, must_exist, done, arg, wait) continue; fatal("error waiting for script %s: %m", prog); } - reap_kids(); + forget_child(pid, status); } return pid; } @@ -1789,6 +1790,35 @@ childwait_end(arg) } /* + * forget_child - clean up after a dead child + */ +static void +forget_child(pid, status) + int pid, status; +{ + struct subprocess *chp, **prevp; + + for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next) { + if (chp->pid == pid) { + --n_children; + *prevp = chp->next; + break; + } + } + if (WIFSIGNALED(status)) { + warn("Child process %s (pid %d) terminated with signal %d", + (chp? chp->prog: "??"), pid, WTERMSIG(status)); + } else if (debug) + dbglog("Script %s finished (pid %d), status = 0x%x", + (chp? chp->prog: "??"), pid, + WIFEXITED(status) ? WEXITSTATUS(status) : status); + if (chp && chp->done) + (*chp->done)(chp->arg); + if (chp) + free(chp); +} + +/* * reap_kids - get status from any dead child processes, * and log a message for abnormal terminations. */ @@ -1796,29 +1826,11 @@ static int reap_kids() { int pid, status; - struct subprocess *chp, **prevp; if (n_children == 0) return 0; while ((pid = waitpid(-1, &status, WNOHANG)) != -1 && pid != 0) { - for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next) { - if (chp->pid == pid) { - --n_children; - *prevp = chp->next; - break; - } - } - if (WIFSIGNALED(status)) { - warn("Child process %s (pid %d) terminated with signal %d", - (chp? chp->prog: "??"), pid, WTERMSIG(status)); - } else if (debug) - dbglog("Script %s finished (pid %d), status = 0x%x", - (chp? chp->prog: "??"), pid, - WIFEXITED(status) ? WEXITSTATUS(status) : status); - if (chp && chp->done) - (*chp->done)(chp->arg); - if (chp) - free(chp); + forget_child(pid, status); } if (pid == -1) { if (errno == ECHILD) |