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