File: pty_command_timeout

package info (click to toggle)
ppp 2.4.5-4%2Bdeb6u2
  • links: PTS
  • area: main
  • in suites: squeeze-lts
  • size: 3,808 kB
  • ctags: 5,983
  • sloc: ansic: 54,378; sh: 1,030; perl: 250; makefile: 132; exp: 82
file content (129 lines) | stat: -rw-r--r-- 3,037 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
this patch is broken

diff -ur ppp.orig/pppd/main.c ppp/pppd/main.c
--- ppp.orig/pppd/main.c	Tue Sep 23 12:15:22 2003
+++ ppp/pppd/main.c	Thu Jan 15 12:04:28 2004
@@ -624,7 +624,7 @@
     }
 
     /* Wait for scripts to finish */
-    /* XXX should have a timeout here */
+    /* timeout is handled by "reap_kids(1)" */
     while (n_children > 0) {
 	if (debug) {
 	    struct subprocess *chp;
@@ -1710,40 +1710,95 @@
 reap_kids(waitfor)
     int waitfor;
 {
-    int pid, status;
+    int pid, status, signal_cnt, signal_num;
     struct subprocess *chp, **prevp;
 
+    signal_cnt = 0;
+
     if (n_children == 0)
-	return 0;
-    while ((pid = waitpid(-1, &status, (waitfor? 0: WNOHANG))) != -1
-	   && pid != 0) {
-	for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next) {
+      return 0; /* there is no kid active */
+
+    while (1) {
+
+      pid = waitpid(-1, &status, WNOHANG);
+      if (pid == -1) {
+	/* waitpid error */
+	if (errno == ECHILD)
+	  return -1;
+	if (errno != EINTR)
+	  error("Error waiting for child process: %m");
+	break; /* exit while loop */
+
+      } else {
+	/* waitpid success */
+
+	if (pid == 0) {
+	  /* kids are running */
+	  if (waitfor == 0)
+	    /* we do not want to wait for kids... */
+	    break; /* exit while loop */
+
+	  /* send kids a signal */
+	  signal_num = 0;
+	  signal_cnt++;
+	  switch (signal_cnt) {
+	  case 1:
+	    signal_num = SIGTERM;
+	    break;
+	  case 2:
+	    signal_num = SIGQUIT;
+	    break;
+	  default:
+	    signal_num = SIGKILL;
+	    signal_cnt--;
+	    break;
+	  }
+	  for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next) {
+	    if (debug) {
+	      dbglog("  Sending signal %d to pid %d", signal_num, chp->pid);
+	    }
+	    kill(chp->pid,signal_num);
+	  }
+	  if (signal_num != SIGKILL) {
+	    if (debug)
+	      dbglog("  Waiting 2 seconds for children to finish");
+	    sleep(2);
+	  }
+
+	} else {
+	  
+	  /* a kid has finished */
+
+	  /* update number of active kids */
+	  for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next) {
 	    if (chp->pid == pid) {
-		--n_children;
-		*prevp = chp->next;
-		break;
+	      --n_children;
+	      *prevp = chp->next;
+	      break;
 	    }
-	}
-	if (WIFSIGNALED(status)) {
+	  }
+	  
+	  if (WIFSIGNALED(status)) {
 	    warn("Child process %s (pid %d) terminated with signal %d",
 		 (chp? chp->prog: "??"), pid, WTERMSIG(status));
-	} else if (debug)
+	  } 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)
+	  if (chp && chp->done)
 	    (*chp->done)(chp->arg);
-	if (chp)
+	  if (chp)
 	    free(chp);
+
+	  break; /* exit while loop */
+	}
+	
+      }
     }
-    if (pid == -1) {
-	if (errno == ECHILD)
-	    return -1;
-	if (errno != EINTR)
-	    error("Error waiting for child process: %m");
-    }
+
     return 0;
 }
+    
 
 /*
  * add_notifier - add a new function to be called when something happens.