summaryrefslogtreecommitdiff
path: root/pppd/main.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2008-06-23 11:47:18 +0000
committerPaul Mackerras <paulus@samba.org>2008-06-23 11:47:18 +0000
commit7e54469ed4f3c2ecc1006475dcd10df1d1fe35d3 (patch)
tree19515ad17d301e8b4018fb0bfe2f68b127425172 /pppd/main.c
parent8f09debe1ccab6c267f1d803bfa6facdd30b56e0 (diff)
downloadppp-7e54469ed4f3c2ecc1006475dcd10df1d1fe35d3.tar.gz
Only kill the whole process group if we have detached
Previously we always sent a signal to the whole of our current process group when we got a signal such as SIGINT or SIGTERM. That's OK if we have detached, because then we have our own process group, but not if we haven't, because there might be other processes in our process group that we don't know about. In the latter case we now just send the signal individually to the child processes that we have forked off to run things like the connect script, charshunt or pty command.
Diffstat (limited to 'pppd/main.c')
-rw-r--r--pppd/main.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/pppd/main.c b/pppd/main.c
index c03fd43..4e1952b 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.155 2006/12/19 10:22:11 paulus Exp $"
+#define RCSID "$Id: main.c,v 1.156 2008/06/23 11:47:18 paulus Exp $"
#include <stdio.h>
#include <ctype.h>
@@ -220,6 +220,7 @@ struct subprocess {
char *prog;
void (*done) __P((void *));
void *arg;
+ int killable;
struct subprocess *next;
};
@@ -1383,7 +1384,21 @@ kill_my_pg(sig)
int sig;
{
struct sigaction act, oldact;
+ struct subprocess *chp;
+
+ if (!detached) {
+ /*
+ * There might be other things in our process group that we
+ * didn't start that would get hit if we did a kill(0), so
+ * just send the signal individually to our children.
+ */
+ for (chp = children; chp != NULL; chp = chp->next)
+ if (chp->killable)
+ kill(chp->pid, sig);
+ return;
+ }
+ /* We've done a setsid(), so we can just use a kill(0) */
sigemptyset(&act.sa_mask); /* unnecessary in fact */
act.sa_handler = SIG_IGN;
act.sa_flags = 0;
@@ -1633,15 +1648,15 @@ device_script(program, in, out, dont_wait)
}
if (pid != 0) {
- if (dont_wait) {
- record_child(pid, program, NULL, NULL);
- status = 0;
- } else {
+ record_child(pid, program, NULL, NULL, 1);
+ status = 0;
+ if (!dont_wait) {
while (waitpid(pid, &status, 0) < 0) {
if (errno == EINTR)
continue;
fatal("error waiting for (dis)connection process: %m");
}
+ forget_child(pid, status);
--conn_running;
}
return (status == 0 ? 0 : -1);
@@ -1663,7 +1678,7 @@ device_script(program, in, out, dont_wait)
/*
- * run-program - execute a program with given arguments,
+ * run_program - execute a program with given arguments,
* but don't wait for it unless wait is non-zero.
* If the program can't be executed, logs an error unless
* must_exist is 0 and the program file doesn't exist.
@@ -1706,7 +1721,7 @@ run_program(prog, args, must_exist, done, arg, wait)
if (pid != 0) {
if (debug)
dbglog("Script %s started (pid %d)", prog, pid);
- record_child(pid, prog, done, arg);
+ record_child(pid, prog, done, arg, 0);
if (wait) {
while (waitpid(pid, &status, 0) < 0) {
if (errno == EINTR)
@@ -1749,11 +1764,12 @@ run_program(prog, args, must_exist, done, arg, wait)
* to use.
*/
void
-record_child(pid, prog, done, arg)
+record_child(pid, prog, done, arg, killable)
int pid;
char *prog;
void (*done) __P((void *));
void *arg;
+ int killable;
{
struct subprocess *chp;
@@ -1768,6 +1784,7 @@ record_child(pid, prog, done, arg)
chp->done = done;
chp->arg = arg;
chp->next = children;
+ chp->killable = killable;
children = chp;
}
}