b46962e5179015ee4b9c8303e7f14ccf1fd668bb
[gnulib.git] / lib / wait-process.c
1 /* Waiting for a subprocess to finish.
2    Copyright (C) 2001-2003, 2005-2008 Free Software Foundation, Inc.
3    Written by Bruno Haible <haible@clisp.cons.org>, 2001.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18
19 #include <config.h>
20
21 /* Specification.  */
22 #include "wait-process.h"
23
24 #include <errno.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <signal.h>
28
29 #include <sys/types.h>
30
31 #if defined _MSC_VER || defined __MINGW32__
32
33 /* Native Woe32 API.  */
34 #include <process.h>
35 #define waitpid(pid,statusp,options) _cwait (statusp, pid, WAIT_CHILD)
36 #define WTERMSIG(x) ((x) & 0xff) /* or: SIGABRT ?? */
37 #define WCOREDUMP(x) 0
38 #define WEXITSTATUS(x) (((x) >> 8) & 0xff) /* or: (x) ?? */
39 #define WIFSIGNALED(x) (WTERMSIG (x) != 0) /* or: ((x) == 3) ?? */
40 #define WIFEXITED(x) (WTERMSIG (x) == 0) /* or: ((x) != 3) ?? */
41 #define WIFSTOPPED(x) 0
42
43 #else
44
45 /* Unix API.  */
46 #include <sys/wait.h>
47 /* On Linux, WEXITSTATUS are bits 15..8 and WTERMSIG are bits 7..0, while
48    BeOS uses the contrary.  Therefore we use the abstract macros.  */
49 #ifndef WTERMSIG
50 # define WTERMSIG(x) ((x) & 0x7f)
51 #endif
52 #ifndef WCOREDUMP
53 # define WCOREDUMP(x) ((x) & 0x80)
54 #endif
55 #ifndef WEXITSTATUS
56 # define WEXITSTATUS(x) (((x) >> 8) & 0xff)
57 #endif
58 /* For valid x, exactly one of WIFSIGNALED(x), WIFEXITED(x), WIFSTOPPED(x)
59    is true.  */
60 #ifndef WIFSIGNALED
61 # define WIFSIGNALED(x) (WTERMSIG (x) != 0 && WTERMSIG(x) != 0x7f)
62 #endif
63 #ifndef WIFEXITED
64 # define WIFEXITED(x) (WTERMSIG (x) == 0)
65 #endif
66 #ifndef WIFSTOPPED
67 # define WIFSTOPPED(x) (WTERMSIG (x) == 0x7f)
68 #endif
69 /* Note that portable applications may access
70    WTERMSIG(x) only if WIFSIGNALED(x) is true, and
71    WEXITSTATUS(x) only if WIFEXITED(x) is true.  */
72
73 #endif
74
75 #include "error.h"
76 #include "fatal-signal.h"
77 #include "xalloc.h"
78 #include "gettext.h"
79
80 #define _(str) gettext (str)
81
82 #define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
83
84
85 #if defined _MSC_VER || defined __MINGW32__
86
87 #define WIN32_LEAN_AND_MEAN
88 #include <windows.h>
89
90 /* The return value of spawnvp() is really a process handle as returned
91    by CreateProcess().  Therefore we can kill it using TerminateProcess.  */
92 #define kill(pid,sig) TerminateProcess ((HANDLE) (pid), sig)
93
94 #endif
95
96
97 /* Type of an entry in the slaves array.
98    The 'used' bit determines whether this entry is currently in use.
99    (If pid_t was an atomic type like sig_atomic_t, we could just set the
100    'child' field to 0 when unregistering a slave process, and wouldn't need
101    the 'used' field.)
102    The 'used' and 'child' fields are accessed from within the cleanup_slaves()
103    action, therefore we mark them as 'volatile'.  */
104 typedef struct
105 {
106   volatile sig_atomic_t used;
107   volatile pid_t child;
108 }
109 slaves_entry_t;
110
111 /* The registered slave subprocesses.  */
112 static slaves_entry_t static_slaves[32];
113 static slaves_entry_t * volatile slaves = static_slaves;
114 static sig_atomic_t volatile slaves_count = 0;
115 static size_t slaves_allocated = SIZEOF (static_slaves);
116
117 /* The termination signal for slave subprocesses.
118    2003-10-07:  Terminator becomes Governator.  */
119 #ifdef SIGHUP
120 # define TERMINATOR SIGHUP
121 #else
122 # define TERMINATOR SIGTERM
123 #endif
124
125 /* The cleanup action.  It gets called asynchronously.  */
126 static void
127 cleanup_slaves (void)
128 {
129   for (;;)
130     {
131       /* Get the last registered slave.  */
132       size_t n = slaves_count;
133       if (n == 0)
134         break;
135       n--;
136       slaves_count = n;
137       /* Skip unused entries in the slaves array.  */
138       if (slaves[n].used)
139         {
140           pid_t slave = slaves[n].child;
141
142           /* Kill the slave.  */
143           kill (slave, TERMINATOR);
144         }
145     }
146 }
147
148 /* Register a subprocess as being a slave process.  This means that the
149    subprocess will be terminated when its creator receives a catchable fatal
150    signal or exits normally.  Registration ends when wait_subprocess()
151    notices that the subprocess has exited.  */
152 void
153 register_slave_subprocess (pid_t child)
154 {
155   static bool cleanup_slaves_registered = false;
156   if (!cleanup_slaves_registered)
157     {
158       atexit (cleanup_slaves);
159       at_fatal_signal (cleanup_slaves);
160       cleanup_slaves_registered = true;
161     }
162
163   /* Try to store the new slave in an unused entry of the slaves array.  */
164   {
165     slaves_entry_t *s = slaves;
166     slaves_entry_t *s_end = s + slaves_count;
167
168     for (; s < s_end; s++)
169       if (!s->used)
170         {
171           /* The two uses of 'volatile' in the slaves_entry_t type above
172              (and ISO C 99 section 5.1.2.3.(5)) ensure that we mark the
173              entry as used only after the child pid has been written to the
174              memory location s->child.  */
175           s->child = child;
176           s->used = 1;
177           return;
178         }
179   }
180
181   if (slaves_count == slaves_allocated)
182     {
183       /* Extend the slaves array.  Note that we cannot use xrealloc(),
184          because then the cleanup_slaves() function could access an already
185          deallocated array.  */
186       slaves_entry_t *old_slaves = slaves;
187       size_t new_slaves_allocated = 2 * slaves_allocated;
188       slaves_entry_t *new_slaves =
189         (slaves_entry_t *)
190         malloc (new_slaves_allocated * sizeof (slaves_entry_t));
191       if (new_slaves == NULL)
192         {
193           /* xalloc_die() will call exit() which will invoke cleanup_slaves().
194              Additionally we need to kill child, because it's not yet among
195              the slaves list.  */
196           kill (child, TERMINATOR);
197           xalloc_die ();
198         }
199       memcpy (new_slaves, old_slaves,
200               slaves_allocated * sizeof (slaves_entry_t));
201       slaves = new_slaves;
202       slaves_allocated = new_slaves_allocated;
203       /* Now we can free the old slaves array.  */
204       if (old_slaves != static_slaves)
205         free (old_slaves);
206     }
207   /* The three uses of 'volatile' in the types above (and ISO C 99 section
208      5.1.2.3.(5)) ensure that we increment the slaves_count only after the
209      new slave and its 'used' bit have been written to the memory locations
210      that make up slaves[slaves_count].  */
211   slaves[slaves_count].child = child;
212   slaves[slaves_count].used = 1;
213   slaves_count++;
214 }
215
216 /* Unregister a child from the list of slave subprocesses.  */
217 static inline void
218 unregister_slave_subprocess (pid_t child)
219 {
220   /* The easiest way to remove an entry from a list that can be used by
221      an asynchronous signal handler is just to mark it as unused.  For this,
222      we rely on sig_atomic_t.  */
223   slaves_entry_t *s = slaves;
224   slaves_entry_t *s_end = s + slaves_count;
225
226   for (; s < s_end; s++)
227     if (s->used && s->child == child)
228       s->used = 0;
229 }
230
231
232 /* Wait for a subprocess to finish.  Return its exit code.
233    If it didn't terminate correctly, exit if exit_on_error is true, otherwise
234    return 127.  */
235 int
236 wait_subprocess (pid_t child, const char *progname,
237                  bool ignore_sigpipe, bool null_stderr,
238                  bool slave_process, bool exit_on_error,
239                  int *termsigp)
240 {
241 #if HAVE_WAITID && defined WNOWAIT && 0
242   /* Commented out because waitid() without WEXITED and with WNOWAIT doesn't
243      work: On Solaris 7 and OSF/1 4.0, it returns -1 and sets errno = ECHILD,
244      and on HP-UX 10.20 it just hangs.  */
245   /* Use of waitid() with WNOWAIT avoids a race condition: If slave_process is
246      true, and this process sleeps a very long time between the return from
247      waitpid() and the execution of unregister_slave_subprocess(), and
248      meanwhile another process acquires the same PID as child, and then - still
249      before unregister_slave_subprocess() - this process gets a fatal signal,
250      it would kill the other totally unrelated process.  */
251   siginfo_t info;
252
253   if (termsigp != NULL)
254     *termsigp = 0;
255   for (;;)
256     {
257       if (waitid (P_PID, child, &info, WEXITED | (slave_process ? WNOWAIT : 0))
258           < 0)
259         {
260 # ifdef EINTR
261           if (errno == EINTR)
262             continue;
263 # endif
264           if (exit_on_error || !null_stderr)
265             error (exit_on_error ? EXIT_FAILURE : 0, errno,
266                    _("%s subprocess"), progname);
267           return 127;
268         }
269
270       /* info.si_code is set to one of CLD_EXITED, CLD_KILLED, CLD_DUMPED,
271          CLD_TRAPPED, CLD_STOPPED, CLD_CONTINUED.  Loop until the program
272          terminates.  */
273       if (info.si_code == CLD_EXITED
274           || info.si_code == CLD_KILLED || info.si_code == CLD_DUMPED)
275         break;
276     }
277
278   /* The child process has exited or was signalled.  */
279
280   if (slave_process)
281     {
282       /* Unregister the child from the list of slave subprocesses, so that
283          later, when we exit, we don't kill a totally unrelated process which
284          may have acquired the same pid.  */
285       unregister_slave_subprocess (child);
286
287       /* Now remove the zombie from the process list.  */
288       for (;;)
289         {
290           if (waitid (P_PID, child, &info, WEXITED) < 0)
291             {
292 # ifdef EINTR
293               if (errno == EINTR)
294                 continue;
295 # endif
296               if (exit_on_error || !null_stderr)
297                 error (exit_on_error ? EXIT_FAILURE : 0, errno,
298                        _("%s subprocess"), progname);
299               return 127;
300             }
301           break;
302         }
303     }
304
305   switch (info.si_code)
306     {
307     case CLD_KILLED:
308     case CLD_DUMPED:
309       if (termsigp != NULL)
310         *termsigp = info.si_status; /* TODO: or info.si_signo? */
311 # ifdef SIGPIPE
312       if (info.si_status == SIGPIPE && ignore_sigpipe)
313         return 0;
314 # endif
315       if (exit_on_error || !null_stderr)
316         error (exit_on_error ? EXIT_FAILURE : 0, 0,
317                _("%s subprocess got fatal signal %d"),
318                progname, info.si_status);
319       return 127;
320     case CLD_EXITED:
321       if (info.si_status == 127)
322         {
323           if (exit_on_error || !null_stderr)
324             error (exit_on_error ? EXIT_FAILURE : 0, 0,
325                    _("%s subprocess failed"), progname);
326           return 127;
327         }
328       return info.si_status;
329     default:
330       abort ();
331     }
332 #else
333   /* waitpid() is just as portable as wait() nowadays.  */
334   int status;
335
336   if (termsigp != NULL)
337     *termsigp = 0;
338   *(int *) &status = 0;
339   for (;;)
340     {
341       int result = waitpid (child, &status, 0);
342
343       if (result != child)
344         {
345 # ifdef EINTR
346           if (errno == EINTR)
347             continue;
348 # endif
349 # if 0 /* defined ECHILD */
350           if (errno == ECHILD)
351             {
352               /* Child process nonexistent?! Assume it terminated
353                  successfully.  */
354               *(int *) &status = 0;
355               break;
356             }
357 # endif
358           if (exit_on_error || !null_stderr)
359             error (exit_on_error ? EXIT_FAILURE : 0, errno,
360                    _("%s subprocess"), progname);
361           return 127;
362         }
363
364       /* One of WIFSIGNALED (status), WIFEXITED (status), WIFSTOPPED (status)
365          must always be true, since we did not specify WCONTINUED in the
366          waitpid() call.  Loop until the program terminates.  */
367       if (!WIFSTOPPED (status))
368         break;
369     }
370
371   /* The child process has exited or was signalled.  */
372
373   if (slave_process)
374     /* Unregister the child from the list of slave subprocesses, so that
375        later, when we exit, we don't kill a totally unrelated process which
376        may have acquired the same pid.  */
377     unregister_slave_subprocess (child);
378
379   if (WIFSIGNALED (status))
380     {
381       if (termsigp != NULL)
382         *termsigp = WTERMSIG (status);
383 # ifdef SIGPIPE
384       if (WTERMSIG (status) == SIGPIPE && ignore_sigpipe)
385         return 0;
386 # endif
387       if (exit_on_error || !null_stderr)
388         error (exit_on_error ? EXIT_FAILURE : 0, 0,
389                _("%s subprocess got fatal signal %d"),
390                progname, (int) WTERMSIG (status));
391       return 127;
392     }
393   if (!WIFEXITED (status))
394     abort ();
395   if (WEXITSTATUS (status) == 127)
396     {
397       if (exit_on_error || !null_stderr)
398         error (exit_on_error ? EXIT_FAILURE : 0, 0,
399                _("%s subprocess failed"), progname);
400       return 127;
401     }
402   return WEXITSTATUS (status);
403 #endif
404 }