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