chiark / gitweb /
wip new states
[innduct.git] / innd / proc.c
1 /*  $Id: proc.c 6124 2003-01-14 06:03:29Z rra $
2 **
3 **  Process control routines.
4 */
5
6 #include "config.h"
7 #include "clibrary.h"
8 #include "portable/wait.h"
9
10 #include "innd.h"
11
12
13 static PROCESS  *PROCtable;
14 static int      PROCtablesize;
15 static PROCESS  PROCnull = { PSfree, 0, 0, 0, 0, 0 };
16
17
18 /*
19 **  Collect dead processes.
20 */
21 static void
22 PROCreap(void)
23 {
24     int         status;
25     PROCESS     *pp;
26     int         i;
27     pid_t       pid;
28
29     for ( ; ; ) {
30         pid = waitpid(-1, &status, WNOHANG);
31         if (pid == 0)
32             break;
33         if (pid < 0) {
34             if (errno != ECHILD)
35                 syslog(L_ERROR, "%s cant wait %m", LogName);
36             break;
37         }
38         for (pp = PROCtable, i = PROCtablesize; --i >= 0; pp++)
39             if (pp->Pid == pid) {
40                 PROCneedscan = true;
41                 pp->Status = WEXITSTATUS(status);
42                 pp->State = PSdead;
43                 pp->Collected = Now.time;
44                 break;
45             }
46     }
47 }
48
49
50 /*
51 **  Signal handler that collects the processes, then resets the signal.
52 */
53 static RETSIGTYPE
54 PROCcatchsignal(int s)
55 {
56     PROCreap();
57
58 #ifndef HAVE_SIGACTION
59     xsignal(s, PROCcatchsignal);
60 #else
61     s = s;                      /* ARGSUSED */
62 #endif
63 }
64
65
66 /*
67 **  Synchronous version that notifies a site when its process went away.
68 */
69 void
70 PROCscan(void)
71 {
72     PROCESS     *pp;
73     int i;
74
75     for (pp = PROCtable, i = PROCtablesize; --i >= 0; pp++)
76         if (pp->State == PSdead) {
77             if (pp->Site >= 0)
78                 SITEprocdied(&Sites[pp->Site], pp - PROCtable, pp);
79             pp->State = PSfree;
80         }
81     PROCneedscan = false;
82 }
83
84
85 #if     0
86 /*
87 **  Close down all processes.
88 */
89 void
90 PROCclose(Quickly)
91     bool                Quickly;
92 {
93     int sig;
94     PROCESS     *pp;
95     int i;
96
97     /* What signal are we sending? */
98     sig = Quickly ? SIGKILL : SIGTERM;
99
100     /* Send the signal to all living processes. */
101     for (pp = PROCtable, i = PROCtablesize; --i >= 0; pp++) {
102         if (pp->State != PSrunning)
103             continue;
104         if (kill(pp->Pid, sig) < 0 && errno != ESRCH)
105             syslog(L_ERROR, "%s cant kill %s %ld %m",
106                 LogName, Quickly ? "KILL" : "TERM", (long) pp->Pid);
107     }
108
109     /* Collect any who might have died. */
110     PROCreap();
111     for (pp = PROCtable, i = PROCtablesize; --i >= 0; pp++)
112         if (pp->State == PSdead)
113             *pp = PROCnull;
114 }
115 #endif  /* 0 */
116
117
118 /*
119 **  Stop watching a process -- we don't care about it any more.
120 */
121 void
122 PROCunwatch(int process)
123 {
124     if (process < 0 || process >= PROCtablesize) {
125         syslog(L_ERROR, "%s internal PROCunwatch %d", LogName, process);
126         return;
127     }
128     PROCtable[process].Site = -1;
129 }
130
131
132 /*
133 **  Add a pid to the list of processes we watch.
134 */
135 int
136 PROCwatch(pid_t pid, int site)
137 {
138     PROCESS     *pp;
139     int         i;
140
141     /* Find a free slot for this process. */
142     for (pp = PROCtable, i = PROCtablesize; --i >= 0; pp++)
143         if (pp->State == PSfree)
144             break;
145     if (i < 0) {
146         /* Ran out of room -- grow the table. */
147         PROCtable = xrealloc(PROCtable, (PROCtablesize + 20) * sizeof(PROCESS));
148         for (pp = &PROCtable[PROCtablesize], i=20; --i >= 0; pp++)
149           *pp = PROCnull;
150         pp = &PROCtable[PROCtablesize];
151         PROCtablesize += 20;
152     }
153
154     pp->State = PSrunning;
155     pp->Pid = pid;
156     pp->Started = Now.time;
157     pp->Site = site;
158     return pp - PROCtable;
159 }
160
161
162 /*
163 **  Setup.
164 */
165 void
166 PROCsetup(int i)
167 {
168     PROCESS     *pp;
169
170     if (PROCtable)
171         free(PROCtable);
172     PROCtablesize = i;
173     PROCtable = xmalloc(PROCtablesize * sizeof(PROCESS));
174     for (pp = PROCtable, i = PROCtablesize; --i >= 0; pp++)
175         *pp = PROCnull;
176
177 #if     defined(SIGCHLD)
178     xsignal(SIGCHLD, PROCcatchsignal);
179 #endif  /* defined(SIGCHLD) */
180     xsignal(SIGPIPE, PROCcatchsignal);
181 }