Mercurial > hg > octave-nkf > gnulib-hg
annotate lib/wait-process.c @ 17907:0a1c2535cad9
euidaccess: Fix Android build
* modules/euidaccess (Depends-on): Add fcntl-h to ensure that
AT_EACCESS gets declared.
author | Kevin Cernekee <cernekee@google.com> |
---|---|
date | Wed, 11 Feb 2015 15:22:54 -0800 |
parents | ab58d4870664 |
children |
rev | line source |
---|---|
4802 | 1 /* Waiting for a subprocess to finish. |
17848 | 2 Copyright (C) 2001-2003, 2005-2015 Free Software Foundation, Inc. |
4802 | 3 Written by Bruno Haible <haible@clisp.cons.org>, 2001. |
4 | |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8196
diff
changeset
|
5 This program is free software: you can redistribute it and/or modify |
4802 | 6 it under the terms of the GNU General Public License as published by |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8196
diff
changeset
|
7 the Free Software Foundation; either version 3 of the License, or |
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8196
diff
changeset
|
8 (at your option) any later version. |
4802 | 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 | |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8196
diff
changeset
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
4802 | 17 |
18 | |
7304
1c4ed7637c24
Include <config.h> unconditionally.
Bruno Haible <bruno@clisp.org>
parents:
7028
diff
changeset
|
19 #include <config.h> |
4802 | 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 #include <sys/wait.h> | |
31 | |
32 #include "error.h" | |
33 #include "fatal-signal.h" | |
34 #include "xalloc.h" | |
35 #include "gettext.h" | |
36 | |
37 #define _(str) gettext (str) | |
38 | |
39 #define SIZEOF(a) (sizeof(a) / sizeof(a[0])) | |
40 | |
41 | |
4847 | 42 #if defined _MSC_VER || defined __MINGW32__ |
43 | |
4927 | 44 #define WIN32_LEAN_AND_MEAN |
45 #include <windows.h> | |
46 | |
4847 | 47 /* The return value of spawnvp() is really a process handle as returned |
48 by CreateProcess(). Therefore we can kill it using TerminateProcess. */ | |
49 #define kill(pid,sig) TerminateProcess ((HANDLE) (pid), sig) | |
50 | |
51 #endif | |
52 | |
53 | |
4802 | 54 /* Type of an entry in the slaves array. |
55 The 'used' bit determines whether this entry is currently in use. | |
56 (If pid_t was an atomic type like sig_atomic_t, we could just set the | |
57 'child' field to 0 when unregistering a slave process, and wouldn't need | |
58 the 'used' field.) | |
59 The 'used' and 'child' fields are accessed from within the cleanup_slaves() | |
60 action, therefore we mark them as 'volatile'. */ | |
61 typedef struct | |
62 { | |
63 volatile sig_atomic_t used; | |
64 volatile pid_t child; | |
65 } | |
66 slaves_entry_t; | |
67 | |
68 /* The registered slave subprocesses. */ | |
69 static slaves_entry_t static_slaves[32]; | |
70 static slaves_entry_t * volatile slaves = static_slaves; | |
71 static sig_atomic_t volatile slaves_count = 0; | |
72 static size_t slaves_allocated = SIZEOF (static_slaves); | |
73 | |
74 /* The termination signal for slave subprocesses. | |
75 2003-10-07: Terminator becomes Governator. */ | |
76 #ifdef SIGHUP | |
77 # define TERMINATOR SIGHUP | |
78 #else | |
79 # define TERMINATOR SIGTERM | |
80 #endif | |
81 | |
82 /* The cleanup action. It gets called asynchronously. */ | |
83 static void | |
4927 | 84 cleanup_slaves (void) |
4802 | 85 { |
86 for (;;) | |
87 { | |
88 /* Get the last registered slave. */ | |
89 size_t n = slaves_count; | |
90 if (n == 0) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
91 break; |
4802 | 92 n--; |
93 slaves_count = n; | |
94 /* Skip unused entries in the slaves array. */ | |
95 if (slaves[n].used) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
96 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
97 pid_t slave = slaves[n].child; |
4802 | 98 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
99 /* Kill the slave. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
100 kill (slave, TERMINATOR); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
101 } |
4802 | 102 } |
103 } | |
104 | |
105 /* Register a subprocess as being a slave process. This means that the | |
106 subprocess will be terminated when its creator receives a catchable fatal | |
107 signal or exits normally. Registration ends when wait_subprocess() | |
108 notices that the subprocess has exited. */ | |
109 void | |
110 register_slave_subprocess (pid_t child) | |
111 { | |
112 static bool cleanup_slaves_registered = false; | |
113 if (!cleanup_slaves_registered) | |
114 { | |
115 atexit (cleanup_slaves); | |
116 at_fatal_signal (cleanup_slaves); | |
117 cleanup_slaves_registered = true; | |
118 } | |
119 | |
120 /* Try to store the new slave in an unused entry of the slaves array. */ | |
121 { | |
122 slaves_entry_t *s = slaves; | |
123 slaves_entry_t *s_end = s + slaves_count; | |
124 | |
125 for (; s < s_end; s++) | |
126 if (!s->used) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
127 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
128 /* The two uses of 'volatile' in the slaves_entry_t type above |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
129 (and ISO C 99 section 5.1.2.3.(5)) ensure that we mark the |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
130 entry as used only after the child pid has been written to the |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
131 memory location s->child. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
132 s->child = child; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
133 s->used = 1; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
134 return; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
135 } |
4802 | 136 } |
137 | |
138 if (slaves_count == slaves_allocated) | |
139 { | |
140 /* Extend the slaves array. Note that we cannot use xrealloc(), | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
141 because then the cleanup_slaves() function could access an already |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
142 deallocated array. */ |
4802 | 143 slaves_entry_t *old_slaves = slaves; |
144 size_t new_slaves_allocated = 2 * slaves_allocated; | |
145 slaves_entry_t *new_slaves = | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
146 (slaves_entry_t *) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
147 malloc (new_slaves_allocated * sizeof (slaves_entry_t)); |
4802 | 148 if (new_slaves == NULL) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
149 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
150 /* xalloc_die() will call exit() which will invoke cleanup_slaves(). |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
151 Additionally we need to kill child, because it's not yet among |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
152 the slaves list. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
153 kill (child, TERMINATOR); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
154 xalloc_die (); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
155 } |
4802 | 156 memcpy (new_slaves, old_slaves, |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
157 slaves_allocated * sizeof (slaves_entry_t)); |
4802 | 158 slaves = new_slaves; |
159 slaves_allocated = new_slaves_allocated; | |
160 /* Now we can free the old slaves array. */ | |
161 if (old_slaves != static_slaves) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
162 free (old_slaves); |
4802 | 163 } |
164 /* The three uses of 'volatile' in the types above (and ISO C 99 section | |
165 5.1.2.3.(5)) ensure that we increment the slaves_count only after the | |
166 new slave and its 'used' bit have been written to the memory locations | |
167 that make up slaves[slaves_count]. */ | |
168 slaves[slaves_count].child = child; | |
169 slaves[slaves_count].used = 1; | |
170 slaves_count++; | |
171 } | |
172 | |
173 /* Unregister a child from the list of slave subprocesses. */ | |
17185
dd46d4e6beea
dup, execute, fatal-signal, etc.: no 'static inline'
Paul Eggert <eggert@cs.ucla.edu>
parents:
16201
diff
changeset
|
174 static void |
4802 | 175 unregister_slave_subprocess (pid_t child) |
176 { | |
177 /* The easiest way to remove an entry from a list that can be used by | |
178 an asynchronous signal handler is just to mark it as unused. For this, | |
179 we rely on sig_atomic_t. */ | |
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 && s->child == child) | |
185 s->used = 0; | |
186 } | |
187 | |
188 | |
189 /* Wait for a subprocess to finish. Return its exit code. | |
190 If it didn't terminate correctly, exit if exit_on_error is true, otherwise | |
191 return 127. */ | |
192 int | |
6761
14eb5491c867
* lib/wait-process.c, lib/wait-process.h, lib/csharpcomp.c,
Derek R. Price <derek@ximbiot.com>
parents:
6759
diff
changeset
|
193 wait_subprocess (pid_t child, const char *progname, |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
194 bool ignore_sigpipe, bool null_stderr, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
195 bool slave_process, bool exit_on_error, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
196 int *termsigp) |
4802 | 197 { |
4927 | 198 #if HAVE_WAITID && defined WNOWAIT && 0 |
10193
b67d0f4f1513
Try to fix waitid() based code.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
199 /* Commented out because waitid() without WEXITED and with WNOWAIT doesn't |
b67d0f4f1513
Try to fix waitid() based code.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
200 work: On Solaris 7 and OSF/1 4.0, it returns -1 and sets errno = ECHILD, |
b67d0f4f1513
Try to fix waitid() based code.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
201 and on HP-UX 10.20 it just hangs. */ |
4847 | 202 /* Use of waitid() with WNOWAIT avoids a race condition: If slave_process is |
203 true, and this process sleeps a very long time between the return from | |
204 waitpid() and the execution of unregister_slave_subprocess(), and | |
205 meanwhile another process acquires the same PID as child, and then - still | |
206 before unregister_slave_subprocess() - this process gets a fatal signal, | |
207 it would kill the other totally unrelated process. */ | |
208 siginfo_t info; | |
10197
d079dd7b69bc
Add termsigp argument to execute() and wait_process().
Bruno Haible <bruno@clisp.org>
parents:
10194
diff
changeset
|
209 |
d079dd7b69bc
Add termsigp argument to execute() and wait_process().
Bruno Haible <bruno@clisp.org>
parents:
10194
diff
changeset
|
210 if (termsigp != NULL) |
d079dd7b69bc
Add termsigp argument to execute() and wait_process().
Bruno Haible <bruno@clisp.org>
parents:
10194
diff
changeset
|
211 *termsigp = 0; |
4847 | 212 for (;;) |
213 { | |
10193
b67d0f4f1513
Try to fix waitid() based code.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
214 if (waitid (P_PID, child, &info, WEXITED | (slave_process ? WNOWAIT : 0)) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
215 < 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
216 { |
4847 | 217 # ifdef EINTR |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
218 if (errno == EINTR) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
219 continue; |
4847 | 220 # endif |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
221 if (exit_on_error || !null_stderr) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
222 error (exit_on_error ? EXIT_FAILURE : 0, errno, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
223 _("%s subprocess"), progname); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
224 return 127; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
225 } |
4847 | 226 |
227 /* info.si_code is set to one of CLD_EXITED, CLD_KILLED, CLD_DUMPED, | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
228 CLD_TRAPPED, CLD_STOPPED, CLD_CONTINUED. Loop until the program |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
229 terminates. */ |
4847 | 230 if (info.si_code == CLD_EXITED |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
231 || info.si_code == CLD_KILLED || info.si_code == CLD_DUMPED) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
232 break; |
4847 | 233 } |
234 | |
235 /* The child process has exited or was signalled. */ | |
236 | |
237 if (slave_process) | |
238 { | |
239 /* Unregister the child from the list of slave subprocesses, so that | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
240 later, when we exit, we don't kill a totally unrelated process which |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
241 may have acquired the same pid. */ |
4847 | 242 unregister_slave_subprocess (child); |
243 | |
244 /* Now remove the zombie from the process list. */ | |
245 for (;;) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
246 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
247 if (waitid (P_PID, child, &info, WEXITED) < 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
248 { |
4847 | 249 # ifdef EINTR |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
250 if (errno == EINTR) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
251 continue; |
4847 | 252 # endif |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
253 if (exit_on_error || !null_stderr) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
254 error (exit_on_error ? EXIT_FAILURE : 0, errno, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
255 _("%s subprocess"), progname); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
256 return 127; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
257 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
258 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
259 } |
4847 | 260 } |
261 | |
262 switch (info.si_code) | |
263 { | |
264 case CLD_KILLED: | |
265 case CLD_DUMPED: | |
10197
d079dd7b69bc
Add termsigp argument to execute() and wait_process().
Bruno Haible <bruno@clisp.org>
parents:
10194
diff
changeset
|
266 if (termsigp != NULL) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
267 *termsigp = info.si_status; /* TODO: or info.si_signo? */ |
4927 | 268 # ifdef SIGPIPE |
269 if (info.si_status == SIGPIPE && ignore_sigpipe) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
270 return 0; |
4927 | 271 # endif |
11248
04d6b677b5e4
Omit an error message that the caller can do better.
Bruno Haible <bruno@clisp.org>
parents:
11247
diff
changeset
|
272 if (exit_on_error || (!null_stderr && termsigp == NULL)) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
273 error (exit_on_error ? EXIT_FAILURE : 0, 0, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
274 _("%s subprocess got fatal signal %d"), |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
275 progname, info.si_status); |
4847 | 276 return 127; |
277 case CLD_EXITED: | |
278 if (info.si_status == 127) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
279 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
280 if (exit_on_error || !null_stderr) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
281 error (exit_on_error ? EXIT_FAILURE : 0, 0, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
282 _("%s subprocess failed"), progname); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
283 return 127; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
284 } |
4847 | 285 return info.si_status; |
286 default: | |
287 abort (); | |
288 } | |
289 #else | |
4802 | 290 /* waitpid() is just as portable as wait() nowadays. */ |
10674
fbb2ccfb180d
Assume that waitpid() fills an 'int' status, not a 'union wait'.
Bruno Haible <bruno@clisp.org>
parents:
10197
diff
changeset
|
291 int status; |
4802 | 292 |
10197
d079dd7b69bc
Add termsigp argument to execute() and wait_process().
Bruno Haible <bruno@clisp.org>
parents:
10194
diff
changeset
|
293 if (termsigp != NULL) |
d079dd7b69bc
Add termsigp argument to execute() and wait_process().
Bruno Haible <bruno@clisp.org>
parents:
10194
diff
changeset
|
294 *termsigp = 0; |
11247 | 295 status = 0; |
4802 | 296 for (;;) |
297 { | |
298 int result = waitpid (child, &status, 0); | |
299 | |
300 if (result != child) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
301 { |
4847 | 302 # ifdef EINTR |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
303 if (errno == EINTR) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
304 continue; |
4847 | 305 # endif |
306 # if 0 /* defined ECHILD */ | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
307 if (errno == ECHILD) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
308 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
309 /* Child process nonexistent?! Assume it terminated |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
310 successfully. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
311 status = 0; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
312 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
313 } |
4847 | 314 # endif |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
315 if (exit_on_error || !null_stderr) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
316 error (exit_on_error ? EXIT_FAILURE : 0, errno, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
317 _("%s subprocess"), progname); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
318 return 127; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
319 } |
4802 | 320 |
321 /* One of WIFSIGNALED (status), WIFEXITED (status), WIFSTOPPED (status) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
322 must always be true, since we did not specify WCONTINUED in the |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
323 waitpid() call. Loop until the program terminates. */ |
4802 | 324 if (!WIFSTOPPED (status)) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
325 break; |
4802 | 326 } |
327 | |
328 /* The child process has exited or was signalled. */ | |
329 | |
330 if (slave_process) | |
331 /* Unregister the child from the list of slave subprocesses, so that | |
332 later, when we exit, we don't kill a totally unrelated process which | |
333 may have acquired the same pid. */ | |
334 unregister_slave_subprocess (child); | |
335 | |
336 if (WIFSIGNALED (status)) | |
337 { | |
10197
d079dd7b69bc
Add termsigp argument to execute() and wait_process().
Bruno Haible <bruno@clisp.org>
parents:
10194
diff
changeset
|
338 if (termsigp != NULL) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
339 *termsigp = WTERMSIG (status); |
4927 | 340 # ifdef SIGPIPE |
341 if (WTERMSIG (status) == SIGPIPE && ignore_sigpipe) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
342 return 0; |
4927 | 343 # endif |
11248
04d6b677b5e4
Omit an error message that the caller can do better.
Bruno Haible <bruno@clisp.org>
parents:
11247
diff
changeset
|
344 if (exit_on_error || (!null_stderr && termsigp == NULL)) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
345 error (exit_on_error ? EXIT_FAILURE : 0, 0, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
346 _("%s subprocess got fatal signal %d"), |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
347 progname, (int) WTERMSIG (status)); |
4802 | 348 return 127; |
349 } | |
10194 | 350 if (!WIFEXITED (status)) |
351 abort (); | |
4802 | 352 if (WEXITSTATUS (status) == 127) |
353 { | |
354 if (exit_on_error || !null_stderr) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
355 error (exit_on_error ? EXIT_FAILURE : 0, 0, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11248
diff
changeset
|
356 _("%s subprocess failed"), progname); |
4802 | 357 return 127; |
358 } | |
359 return WEXITSTATUS (status); | |
4847 | 360 #endif |
4802 | 361 } |