/src/CMake/Source/kwsys/ProcessUNIX.c
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ |
3 | | #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__) |
4 | | /* NOLINTNEXTLINE(bugprone-reserved-identifier) */ |
5 | | # define _XOPEN_SOURCE 600 |
6 | | #endif |
7 | | #include "kwsysPrivate.h" |
8 | | #include KWSYS_HEADER(Process.h) |
9 | | #include KWSYS_HEADER(System.h) |
10 | | |
11 | | /* Work-around CMake dependency scanning limitation. This must |
12 | | duplicate the above list of headers. */ |
13 | | #if 0 |
14 | | # include "Process.h.in" |
15 | | # include "System.h.in" |
16 | | #endif |
17 | | |
18 | | /* |
19 | | |
20 | | Implementation for UNIX |
21 | | |
22 | | On UNIX, a child process is forked to exec the program. Three output |
23 | | pipes are read by the parent process using a select call to block |
24 | | until data are ready. Two of the pipes are stdout and stderr for the |
25 | | child. The third is a special pipe populated by a signal handler to |
26 | | indicate that a child has terminated. This is used in conjunction |
27 | | with the timeout on the select call to implement a timeout for program |
28 | | even when it closes stdout and stderr and at the same time avoiding |
29 | | races. |
30 | | |
31 | | */ |
32 | | |
33 | | /* |
34 | | |
35 | | TODO: |
36 | | |
37 | | We cannot create the pipeline of processes in suspended states. How |
38 | | do we cleanup processes already started when one fails to load? Right |
39 | | now we are just killing them, which is probably not the right thing to |
40 | | do. |
41 | | |
42 | | */ |
43 | | |
44 | | #if defined(__CYGWIN__) |
45 | | /* Increase the file descriptor limit for select() before including |
46 | | related system headers. (Default: 64) */ |
47 | | # define FD_SETSIZE 16384 |
48 | | #elif defined(__APPLE__) |
49 | | /* Increase the file descriptor limit for select() before including |
50 | | related system headers. (Default: 1024) */ |
51 | | # define _DARWIN_UNLIMITED_SELECT |
52 | | # include <limits.h> /* OPEN_MAX */ |
53 | | # define FD_SETSIZE OPEN_MAX |
54 | | #endif |
55 | | |
56 | | #include <assert.h> /* assert */ |
57 | | #include <ctype.h> /* isspace */ |
58 | | #include <dirent.h> /* DIR, dirent */ |
59 | | #include <errno.h> /* errno */ |
60 | | #include <fcntl.h> /* fcntl */ |
61 | | #include <signal.h> /* sigaction */ |
62 | | #include <stddef.h> /* ptrdiff_t */ |
63 | | #include <stdio.h> /* snprintf */ |
64 | | #include <stdlib.h> /* malloc, free */ |
65 | | #include <string.h> /* strdup, strerror, memset */ |
66 | | #include <sys/stat.h> /* open mode */ |
67 | | #include <sys/time.h> /* struct timeval */ |
68 | | #include <sys/types.h> /* pid_t, fd_set */ |
69 | | #include <sys/wait.h> /* waitpid */ |
70 | | #include <time.h> /* gettimeofday */ |
71 | | #include <unistd.h> /* pipe, close, fork, execvp, select, _exit */ |
72 | | |
73 | | #if defined(__VMS) |
74 | | # define KWSYSPE_VMS_NONBLOCK , O_NONBLOCK |
75 | | #else |
76 | | # define KWSYSPE_VMS_NONBLOCK |
77 | | #endif |
78 | | |
79 | | #if defined(KWSYS_C_HAS_PTRDIFF_T) && KWSYS_C_HAS_PTRDIFF_T |
80 | | typedef ptrdiff_t kwsysProcess_ptrdiff_t; |
81 | | #else |
82 | | typedef int kwsysProcess_ptrdiff_t; |
83 | | #endif |
84 | | |
85 | | #if defined(KWSYS_C_HAS_SSIZE_T) && KWSYS_C_HAS_SSIZE_T |
86 | | typedef ssize_t kwsysProcess_ssize_t; |
87 | | #else |
88 | | typedef int kwsysProcess_ssize_t; |
89 | | #endif |
90 | | |
91 | | #if defined(__BEOS__) && !defined(__ZETA__) |
92 | | /* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */ |
93 | | # include <be/kernel/OS.h> |
94 | | static inline void kwsysProcess_usleep(unsigned int msec) |
95 | | { |
96 | | snooze(msec); |
97 | | } |
98 | | #else |
99 | | # define kwsysProcess_usleep usleep |
100 | | #endif |
101 | | |
102 | | /* |
103 | | * BeOS's select() works like WinSock: it's for networking only, and |
104 | | * doesn't work with Unix file handles...socket and file handles are |
105 | | * different namespaces (the same descriptor means different things in |
106 | | * each context!) |
107 | | * |
108 | | * So on Unix-like systems where select() is flakey, we'll set the |
109 | | * pipes' file handles to be non-blocking and just poll them directly |
110 | | * without select(). |
111 | | */ |
112 | | #if !defined(__BEOS__) && !defined(__VMS) && !defined(__MINT__) && \ |
113 | | !defined(KWSYSPE_USE_SELECT) |
114 | | # define KWSYSPE_USE_SELECT 1 |
115 | | #endif |
116 | | |
117 | | /* Some platforms do not have siginfo on their signal handlers. */ |
118 | | #if defined(SA_SIGINFO) && !defined(__BEOS__) |
119 | | # define KWSYSPE_USE_SIGINFO 1 |
120 | | #endif |
121 | | |
122 | | /* The number of pipes for the child's output. The standard stdout |
123 | | and stderr pipes are the first two. One more pipe is used to |
124 | | detect when the child process has terminated. The third pipe is |
125 | | not given to the child process, so it cannot close it until it |
126 | | terminates. */ |
127 | 0 | #define KWSYSPE_PIPE_COUNT 3 |
128 | 0 | #define KWSYSPE_PIPE_STDOUT 0 |
129 | 0 | #define KWSYSPE_PIPE_STDERR 1 |
130 | 0 | #define KWSYSPE_PIPE_SIGNAL 2 |
131 | | |
132 | | /* The maximum amount to read from a pipe at a time. */ |
133 | 0 | #define KWSYSPE_PIPE_BUFFER_SIZE 1024 |
134 | | |
135 | | #if defined(__NVCOMPILER) |
136 | | # pragma diag_suppress 550 /* variable set but never used (in FD_ZERO) */ |
137 | | #endif |
138 | | |
139 | | /* Keep track of times using a signed representation. Switch to the |
140 | | native (possibly unsigned) representation only when calling native |
141 | | functions. */ |
142 | | typedef struct timeval kwsysProcessTimeNative; |
143 | | typedef struct kwsysProcessTime_s kwsysProcessTime; |
144 | | struct kwsysProcessTime_s |
145 | | { |
146 | | long tv_sec; |
147 | | long tv_usec; |
148 | | }; |
149 | | |
150 | | typedef struct kwsysProcessCreateInformation_s |
151 | | { |
152 | | int StdIn; |
153 | | int StdOut; |
154 | | int StdErr; |
155 | | int ErrorPipe[2]; |
156 | | } kwsysProcessCreateInformation; |
157 | | |
158 | | static void kwsysProcessVolatileFree(void volatile* p); |
159 | | static int kwsysProcessInitialize(kwsysProcess* cp); |
160 | | static void kwsysProcessCleanup(kwsysProcess* cp, int error); |
161 | | static void kwsysProcessCleanupDescriptor(int* pfd); |
162 | | static void kwsysProcessClosePipes(kwsysProcess* cp); |
163 | | static int kwsysProcessSetNonBlocking(int fd); |
164 | | static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, |
165 | | kwsysProcessCreateInformation* si); |
166 | | static void kwsysProcessDestroy(kwsysProcess* cp); |
167 | | static int kwsysProcessSetupOutputPipeFile(int* p, char const* name); |
168 | | static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]); |
169 | | static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, |
170 | | double const* userTimeout, |
171 | | kwsysProcessTime* timeoutTime); |
172 | | static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, |
173 | | double const* userTimeout, |
174 | | kwsysProcessTimeNative* timeoutLength, |
175 | | int zeroIsExpired); |
176 | | static kwsysProcessTime kwsysProcessTimeGetCurrent(void); |
177 | | static double kwsysProcessTimeToDouble(kwsysProcessTime t); |
178 | | static kwsysProcessTime kwsysProcessTimeFromDouble(double d); |
179 | | static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2); |
180 | | static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, |
181 | | kwsysProcessTime in2); |
182 | | static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, |
183 | | kwsysProcessTime in2); |
184 | | static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig, |
185 | | int idx); |
186 | | static void kwsysProcessChildErrorExit(int errorPipe); |
187 | | static void kwsysProcessRestoreDefaultSignalHandlers(void); |
188 | | static pid_t kwsysProcessFork(kwsysProcess* cp, |
189 | | kwsysProcessCreateInformation* si); |
190 | | static void kwsysProcessKill(pid_t process_id); |
191 | | #if defined(__VMS) |
192 | | static int kwsysProcessSetVMSFeature(char const* name, int value); |
193 | | #endif |
194 | | static int kwsysProcessesAdd(kwsysProcess* cp); |
195 | | static void kwsysProcessesRemove(kwsysProcess* cp); |
196 | | #if KWSYSPE_USE_SIGINFO |
197 | | static void kwsysProcessesSignalHandler(int signum, siginfo_t* info, |
198 | | void* ucontext); |
199 | | #else |
200 | | static void kwsysProcessesSignalHandler(int signum); |
201 | | #endif |
202 | | |
203 | | /* A structure containing results data for each process. */ |
204 | | typedef struct kwsysProcessResults_s kwsysProcessResults; |
205 | | struct kwsysProcessResults_s |
206 | | { |
207 | | /* The status of the child process. */ |
208 | | int State; |
209 | | |
210 | | /* The exceptional behavior that terminated the process, if any. */ |
211 | | int ExitException; |
212 | | |
213 | | /* The process exit code. */ |
214 | | int ExitCode; |
215 | | |
216 | | /* The process return code, if any. */ |
217 | | int ExitValue; |
218 | | |
219 | | /* Description for the ExitException. */ |
220 | | char ExitExceptionString[KWSYSPE_PIPE_BUFFER_SIZE + 1]; |
221 | | }; |
222 | | |
223 | | /* Structure containing data used to implement the child's execution. */ |
224 | | struct kwsysProcess_s |
225 | | { |
226 | | /* The command lines to execute. */ |
227 | | char*** Commands; |
228 | | int volatile NumberOfCommands; |
229 | | |
230 | | /* Descriptors for the read ends of the child's output pipes and |
231 | | the signal pipe. */ |
232 | | int PipeReadEnds[KWSYSPE_PIPE_COUNT]; |
233 | | |
234 | | /* Descriptors for the child's ends of the pipes. |
235 | | Used temporarily during process creation. */ |
236 | | int PipeChildStd[3]; |
237 | | |
238 | | /* Write descriptor for child termination signal pipe. */ |
239 | | int SignalPipe; |
240 | | |
241 | | /* Buffer for pipe data. */ |
242 | | char PipeBuffer[KWSYSPE_PIPE_BUFFER_SIZE]; |
243 | | |
244 | | /* Process IDs returned by the calls to fork. Everything is volatile |
245 | | because the signal handler accesses them. You must be very careful |
246 | | when reaping PIDs or modifying this array to avoid race conditions. */ |
247 | | pid_t volatile* volatile ForkPIDs; |
248 | | |
249 | | /* Flag for whether the children were terminated by a failed select. */ |
250 | | int SelectError; |
251 | | |
252 | | /* The timeout length. */ |
253 | | double Timeout; |
254 | | |
255 | | /* The working directory for the process. */ |
256 | | char* WorkingDirectory; |
257 | | |
258 | | /* Whether to create the child as a detached process. */ |
259 | | int OptionDetach; |
260 | | |
261 | | /* Whether the child was created as a detached process. */ |
262 | | int Detached; |
263 | | |
264 | | /* Whether to treat command lines as verbatim. */ |
265 | | int Verbatim; |
266 | | |
267 | | /* Whether to merge stdout/stderr of the child. */ |
268 | | int MergeOutput; |
269 | | |
270 | | /* Whether to create the process in a new process group. */ |
271 | | sig_atomic_t volatile CreateProcessGroup; |
272 | | |
273 | | /* Time at which the child started. Negative for no timeout. */ |
274 | | kwsysProcessTime StartTime; |
275 | | |
276 | | /* Time at which the child will timeout. Negative for no timeout. */ |
277 | | kwsysProcessTime TimeoutTime; |
278 | | |
279 | | /* Flag for whether the timeout expired. */ |
280 | | int TimeoutExpired; |
281 | | |
282 | | /* The number of pipes left open during execution. */ |
283 | | int PipesLeft; |
284 | | |
285 | | #if KWSYSPE_USE_SELECT |
286 | | /* File descriptor set for call to select. */ |
287 | | fd_set PipeSet; |
288 | | #endif |
289 | | |
290 | | /* The number of children still executing. */ |
291 | | int CommandsLeft; |
292 | | |
293 | | /* The status of the process structure. Must be atomic because |
294 | | the signal handler checks this to avoid a race. */ |
295 | | sig_atomic_t volatile State; |
296 | | |
297 | | /* Whether the process was killed. */ |
298 | | sig_atomic_t volatile Killed; |
299 | | |
300 | | /* Buffer for error message in case of failure. */ |
301 | | char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE + 1]; |
302 | | |
303 | | /* process results. */ |
304 | | kwsysProcessResults* ProcessResults; |
305 | | |
306 | | /* The exit codes of each child process in the pipeline. */ |
307 | | int* CommandExitCodes; |
308 | | |
309 | | /* Name of files to which stdin and stdout pipes are attached. */ |
310 | | char* PipeFileSTDIN; |
311 | | char* PipeFileSTDOUT; |
312 | | char* PipeFileSTDERR; |
313 | | |
314 | | /* Whether each pipe is shared with the parent process. */ |
315 | | int PipeSharedSTDIN; |
316 | | int PipeSharedSTDOUT; |
317 | | int PipeSharedSTDERR; |
318 | | |
319 | | /* Native pipes provided by the user. */ |
320 | | int PipeNativeSTDIN[2]; |
321 | | int PipeNativeSTDOUT[2]; |
322 | | int PipeNativeSTDERR[2]; |
323 | | |
324 | | /* The real working directory of this process. */ |
325 | | int RealWorkingDirectoryLength; |
326 | | char* RealWorkingDirectory; |
327 | | }; |
328 | | |
329 | | kwsysProcess* kwsysProcess_New(void) |
330 | 0 | { |
331 | | /* Allocate a process control structure. */ |
332 | 0 | kwsysProcess* cp = (kwsysProcess*)malloc(sizeof(kwsysProcess)); |
333 | 0 | if (!cp) { |
334 | 0 | return 0; |
335 | 0 | } |
336 | 0 | memset(cp, 0, sizeof(kwsysProcess)); |
337 | | |
338 | | /* Share stdin with the parent process by default. */ |
339 | 0 | cp->PipeSharedSTDIN = 1; |
340 | | |
341 | | /* No native pipes by default. */ |
342 | 0 | cp->PipeNativeSTDIN[0] = -1; |
343 | 0 | cp->PipeNativeSTDIN[1] = -1; |
344 | 0 | cp->PipeNativeSTDOUT[0] = -1; |
345 | 0 | cp->PipeNativeSTDOUT[1] = -1; |
346 | 0 | cp->PipeNativeSTDERR[0] = -1; |
347 | 0 | cp->PipeNativeSTDERR[1] = -1; |
348 | | |
349 | | /* Set initial status. */ |
350 | 0 | cp->State = kwsysProcess_State_Starting; |
351 | |
|
352 | 0 | return cp; |
353 | 0 | } |
354 | | |
355 | | void kwsysProcess_Delete(kwsysProcess* cp) |
356 | 0 | { |
357 | | /* Make sure we have an instance. */ |
358 | 0 | if (!cp) { |
359 | 0 | return; |
360 | 0 | } |
361 | | |
362 | | /* If the process is executing, wait for it to finish. */ |
363 | 0 | if (cp->State == kwsysProcess_State_Executing) { |
364 | 0 | if (cp->Detached) { |
365 | 0 | kwsysProcess_Disown(cp); |
366 | 0 | } else { |
367 | 0 | kwsysProcess_WaitForExit(cp, 0); |
368 | 0 | } |
369 | 0 | } |
370 | | |
371 | | /* Free memory. */ |
372 | 0 | kwsysProcess_SetCommand(cp, 0); |
373 | 0 | kwsysProcess_SetWorkingDirectory(cp, 0); |
374 | 0 | kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0); |
375 | 0 | kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0); |
376 | 0 | kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0); |
377 | 0 | free(cp->CommandExitCodes); |
378 | 0 | free(cp->ProcessResults); |
379 | 0 | free(cp); |
380 | 0 | } |
381 | | |
382 | | int kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command) |
383 | 0 | { |
384 | 0 | int i; |
385 | 0 | if (!cp) { |
386 | 0 | return 0; |
387 | 0 | } |
388 | 0 | for (i = 0; i < cp->NumberOfCommands; ++i) { |
389 | 0 | char** c = cp->Commands[i]; |
390 | 0 | while (*c) { |
391 | 0 | free(*c++); |
392 | 0 | } |
393 | 0 | free(cp->Commands[i]); |
394 | 0 | } |
395 | 0 | cp->NumberOfCommands = 0; |
396 | 0 | if (cp->Commands) { |
397 | 0 | free(cp->Commands); |
398 | 0 | cp->Commands = 0; |
399 | 0 | } |
400 | 0 | if (command) { |
401 | 0 | return kwsysProcess_AddCommand(cp, command); |
402 | 0 | } |
403 | 0 | return 1; |
404 | 0 | } |
405 | | |
406 | | int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) |
407 | 0 | { |
408 | 0 | int newNumberOfCommands; |
409 | 0 | char*** newCommands; |
410 | | |
411 | | /* Make sure we have a command to add. */ |
412 | 0 | if (!cp || !command || !*command) { |
413 | 0 | return 0; |
414 | 0 | } |
415 | | |
416 | | /* Allocate a new array for command pointers. */ |
417 | 0 | newNumberOfCommands = cp->NumberOfCommands + 1; |
418 | 0 | if (!(newCommands = |
419 | 0 | (char***)malloc(sizeof(char**) * (size_t)(newNumberOfCommands)))) { |
420 | | /* Out of memory. */ |
421 | 0 | return 0; |
422 | 0 | } |
423 | | |
424 | | /* Copy any existing commands into the new array. */ |
425 | 0 | { |
426 | 0 | int i; |
427 | 0 | for (i = 0; i < cp->NumberOfCommands; ++i) { |
428 | 0 | newCommands[i] = cp->Commands[i]; |
429 | 0 | } |
430 | 0 | } |
431 | | |
432 | | /* Add the new command. */ |
433 | 0 | if (cp->Verbatim) { |
434 | | /* In order to run the given command line verbatim we need to |
435 | | parse it. */ |
436 | 0 | newCommands[cp->NumberOfCommands] = |
437 | 0 | kwsysSystem_Parse_CommandForUnix(*command, 0); |
438 | 0 | if (!newCommands[cp->NumberOfCommands] || |
439 | 0 | !newCommands[cp->NumberOfCommands][0]) { |
440 | | /* Out of memory or no command parsed. */ |
441 | 0 | free(newCommands); |
442 | 0 | return 0; |
443 | 0 | } |
444 | 0 | } else { |
445 | | /* Copy each argument string individually. */ |
446 | 0 | char const* const* c = command; |
447 | 0 | kwsysProcess_ptrdiff_t n = 0; |
448 | 0 | kwsysProcess_ptrdiff_t i = 0; |
449 | 0 | while (*c++) { |
450 | 0 | } |
451 | 0 | n = c - command - 1; |
452 | 0 | newCommands[cp->NumberOfCommands] = |
453 | 0 | (char**)malloc((size_t)(n + 1) * sizeof(char*)); |
454 | 0 | if (!newCommands[cp->NumberOfCommands]) { |
455 | | /* Out of memory. */ |
456 | 0 | free(newCommands); |
457 | 0 | return 0; |
458 | 0 | } |
459 | 0 | for (i = 0; i < n; ++i) { |
460 | 0 | assert(command[i]); /* Quiet Clang scan-build. */ |
461 | 0 | newCommands[cp->NumberOfCommands][i] = strdup(command[i]); |
462 | 0 | if (!newCommands[cp->NumberOfCommands][i]) { |
463 | 0 | break; |
464 | 0 | } |
465 | 0 | } |
466 | 0 | if (i < n) { |
467 | | /* Out of memory. */ |
468 | 0 | for (; i > 0; --i) { |
469 | 0 | free(newCommands[cp->NumberOfCommands][i - 1]); |
470 | 0 | } |
471 | 0 | free(newCommands); |
472 | 0 | return 0; |
473 | 0 | } |
474 | 0 | newCommands[cp->NumberOfCommands][n] = 0; |
475 | 0 | } |
476 | | |
477 | | /* Successfully allocated new command array. Free the old array. */ |
478 | 0 | free(cp->Commands); |
479 | 0 | cp->Commands = newCommands; |
480 | 0 | cp->NumberOfCommands = newNumberOfCommands; |
481 | |
|
482 | 0 | return 1; |
483 | 0 | } |
484 | | |
485 | | void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout) |
486 | 0 | { |
487 | 0 | if (!cp) { |
488 | 0 | return; |
489 | 0 | } |
490 | 0 | cp->Timeout = timeout; |
491 | 0 | if (cp->Timeout < 0) { |
492 | 0 | cp->Timeout = 0; |
493 | 0 | } |
494 | | // Force recomputation of TimeoutTime. |
495 | 0 | cp->TimeoutTime.tv_sec = -1; |
496 | 0 | } |
497 | | |
498 | | int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, char const* dir) |
499 | 0 | { |
500 | 0 | if (!cp) { |
501 | 0 | return 0; |
502 | 0 | } |
503 | 0 | if (cp->WorkingDirectory == dir) { |
504 | 0 | return 1; |
505 | 0 | } |
506 | 0 | if (cp->WorkingDirectory && dir && strcmp(cp->WorkingDirectory, dir) == 0) { |
507 | 0 | return 1; |
508 | 0 | } |
509 | 0 | if (cp->WorkingDirectory) { |
510 | 0 | free(cp->WorkingDirectory); |
511 | 0 | cp->WorkingDirectory = 0; |
512 | 0 | } |
513 | 0 | if (dir) { |
514 | 0 | cp->WorkingDirectory = strdup(dir); |
515 | 0 | if (!cp->WorkingDirectory) { |
516 | 0 | return 0; |
517 | 0 | } |
518 | 0 | } |
519 | 0 | return 1; |
520 | 0 | } |
521 | | |
522 | | int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, char const* file) |
523 | 0 | { |
524 | 0 | char** pfile; |
525 | 0 | if (!cp) { |
526 | 0 | return 0; |
527 | 0 | } |
528 | 0 | switch (prPipe) { |
529 | 0 | case kwsysProcess_Pipe_STDIN: |
530 | 0 | pfile = &cp->PipeFileSTDIN; |
531 | 0 | break; |
532 | 0 | case kwsysProcess_Pipe_STDOUT: |
533 | 0 | pfile = &cp->PipeFileSTDOUT; |
534 | 0 | break; |
535 | 0 | case kwsysProcess_Pipe_STDERR: |
536 | 0 | pfile = &cp->PipeFileSTDERR; |
537 | 0 | break; |
538 | 0 | default: |
539 | 0 | return 0; |
540 | 0 | } |
541 | 0 | if (*pfile) { |
542 | 0 | free(*pfile); |
543 | 0 | *pfile = 0; |
544 | 0 | } |
545 | 0 | if (file) { |
546 | 0 | *pfile = strdup(file); |
547 | 0 | if (!*pfile) { |
548 | 0 | return 0; |
549 | 0 | } |
550 | 0 | } |
551 | | |
552 | | /* If we are redirecting the pipe, do not share it or use a native |
553 | | pipe. */ |
554 | 0 | if (*pfile) { |
555 | 0 | kwsysProcess_SetPipeNative(cp, prPipe, 0); |
556 | 0 | kwsysProcess_SetPipeShared(cp, prPipe, 0); |
557 | 0 | } |
558 | 0 | return 1; |
559 | 0 | } |
560 | | |
561 | | void kwsysProcess_SetPipeShared(kwsysProcess* cp, int prPipe, int shared) |
562 | 0 | { |
563 | 0 | if (!cp) { |
564 | 0 | return; |
565 | 0 | } |
566 | | |
567 | 0 | switch (prPipe) { |
568 | 0 | case kwsysProcess_Pipe_STDIN: |
569 | 0 | cp->PipeSharedSTDIN = shared ? 1 : 0; |
570 | 0 | break; |
571 | 0 | case kwsysProcess_Pipe_STDOUT: |
572 | 0 | cp->PipeSharedSTDOUT = shared ? 1 : 0; |
573 | 0 | break; |
574 | 0 | case kwsysProcess_Pipe_STDERR: |
575 | 0 | cp->PipeSharedSTDERR = shared ? 1 : 0; |
576 | 0 | break; |
577 | 0 | default: |
578 | 0 | return; |
579 | 0 | } |
580 | | |
581 | | /* If we are sharing the pipe, do not redirect it to a file or use a |
582 | | native pipe. */ |
583 | 0 | if (shared) { |
584 | 0 | kwsysProcess_SetPipeFile(cp, prPipe, 0); |
585 | 0 | kwsysProcess_SetPipeNative(cp, prPipe, 0); |
586 | 0 | } |
587 | 0 | } |
588 | | |
589 | | void kwsysProcess_SetPipeNative(kwsysProcess* cp, int prPipe, int const p[2]) |
590 | 0 | { |
591 | 0 | int* pPipeNative = 0; |
592 | |
|
593 | 0 | if (!cp) { |
594 | 0 | return; |
595 | 0 | } |
596 | | |
597 | 0 | switch (prPipe) { |
598 | 0 | case kwsysProcess_Pipe_STDIN: |
599 | 0 | pPipeNative = cp->PipeNativeSTDIN; |
600 | 0 | break; |
601 | 0 | case kwsysProcess_Pipe_STDOUT: |
602 | 0 | pPipeNative = cp->PipeNativeSTDOUT; |
603 | 0 | break; |
604 | 0 | case kwsysProcess_Pipe_STDERR: |
605 | 0 | pPipeNative = cp->PipeNativeSTDERR; |
606 | 0 | break; |
607 | 0 | default: |
608 | 0 | return; |
609 | 0 | } |
610 | | |
611 | | /* Copy the native pipe descriptors provided. */ |
612 | 0 | if (p) { |
613 | 0 | pPipeNative[0] = p[0]; |
614 | 0 | pPipeNative[1] = p[1]; |
615 | 0 | } else { |
616 | 0 | pPipeNative[0] = -1; |
617 | 0 | pPipeNative[1] = -1; |
618 | 0 | } |
619 | | |
620 | | /* If we are using a native pipe, do not share it or redirect it to |
621 | | a file. */ |
622 | 0 | if (p) { |
623 | 0 | kwsysProcess_SetPipeFile(cp, prPipe, 0); |
624 | 0 | kwsysProcess_SetPipeShared(cp, prPipe, 0); |
625 | 0 | } |
626 | 0 | } |
627 | | |
628 | | int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) |
629 | 0 | { |
630 | 0 | if (!cp) { |
631 | 0 | return 0; |
632 | 0 | } |
633 | | |
634 | 0 | switch (optionId) { |
635 | 0 | case kwsysProcess_Option_Detach: |
636 | 0 | return cp->OptionDetach; |
637 | 0 | case kwsysProcess_Option_MergeOutput: |
638 | 0 | return cp->MergeOutput; |
639 | 0 | case kwsysProcess_Option_Verbatim: |
640 | 0 | return cp->Verbatim; |
641 | 0 | case kwsysProcess_Option_CreateProcessGroup: |
642 | 0 | return cp->CreateProcessGroup; |
643 | 0 | default: |
644 | 0 | return 0; |
645 | 0 | } |
646 | 0 | } |
647 | | |
648 | | void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) |
649 | 0 | { |
650 | 0 | if (!cp) { |
651 | 0 | return; |
652 | 0 | } |
653 | | |
654 | 0 | switch (optionId) { |
655 | 0 | case kwsysProcess_Option_Detach: |
656 | 0 | cp->OptionDetach = value; |
657 | 0 | break; |
658 | 0 | case kwsysProcess_Option_MergeOutput: |
659 | 0 | cp->MergeOutput = value; |
660 | 0 | break; |
661 | 0 | case kwsysProcess_Option_Verbatim: |
662 | 0 | cp->Verbatim = value; |
663 | 0 | break; |
664 | 0 | case kwsysProcess_Option_CreateProcessGroup: |
665 | 0 | cp->CreateProcessGroup = value; |
666 | 0 | break; |
667 | 0 | default: |
668 | 0 | break; |
669 | 0 | } |
670 | 0 | } |
671 | | |
672 | | int kwsysProcess_GetState(kwsysProcess* cp) |
673 | 0 | { |
674 | 0 | return cp ? cp->State : kwsysProcess_State_Error; |
675 | 0 | } |
676 | | |
677 | | int kwsysProcess_GetExitException(kwsysProcess* cp) |
678 | 0 | { |
679 | 0 | return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0)) |
680 | 0 | ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitException |
681 | 0 | : kwsysProcess_Exception_Other; |
682 | 0 | } |
683 | | |
684 | | int kwsysProcess_GetExitCode(kwsysProcess* cp) |
685 | 0 | { |
686 | 0 | return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0)) |
687 | 0 | ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitCode |
688 | 0 | : 0; |
689 | 0 | } |
690 | | |
691 | | int kwsysProcess_GetExitValue(kwsysProcess* cp) |
692 | 0 | { |
693 | 0 | return (cp && cp->ProcessResults && (cp->NumberOfCommands > 0)) |
694 | 0 | ? cp->ProcessResults[cp->NumberOfCommands - 1].ExitValue |
695 | 0 | : -1; |
696 | 0 | } |
697 | | |
698 | | char const* kwsysProcess_GetErrorString(kwsysProcess* cp) |
699 | 0 | { |
700 | 0 | if (!cp) { |
701 | 0 | return "Process management structure could not be allocated"; |
702 | 0 | } |
703 | 0 | if (cp->State == kwsysProcess_State_Error) { |
704 | 0 | return cp->ErrorMessage; |
705 | 0 | } |
706 | 0 | return "Success"; |
707 | 0 | } |
708 | | |
709 | | char const* kwsysProcess_GetExceptionString(kwsysProcess* cp) |
710 | 0 | { |
711 | 0 | if (!(cp && cp->ProcessResults && (cp->NumberOfCommands > 0))) { |
712 | 0 | return "GetExceptionString called with NULL process management structure"; |
713 | 0 | } |
714 | 0 | if (cp->State == kwsysProcess_State_Exception) { |
715 | 0 | return cp->ProcessResults[cp->NumberOfCommands - 1].ExitExceptionString; |
716 | 0 | } |
717 | 0 | return "No exception"; |
718 | 0 | } |
719 | | |
720 | | /* the index should be in array bound. */ |
721 | | #define KWSYSPE_IDX_CHK(RET) \ |
722 | 0 | if (!cp || idx >= cp->NumberOfCommands || idx < 0) { \ |
723 | 0 | return RET; \ |
724 | 0 | } |
725 | | |
726 | | int kwsysProcess_GetStateByIndex(kwsysProcess* cp, int idx) |
727 | 0 | { |
728 | 0 | KWSYSPE_IDX_CHK(kwsysProcess_State_Error) |
729 | 0 | return cp->ProcessResults[idx].State; |
730 | 0 | } |
731 | | |
732 | | int kwsysProcess_GetExitExceptionByIndex(kwsysProcess* cp, int idx) |
733 | 0 | { |
734 | 0 | KWSYSPE_IDX_CHK(kwsysProcess_Exception_Other) |
735 | 0 | return cp->ProcessResults[idx].ExitException; |
736 | 0 | } |
737 | | |
738 | | int kwsysProcess_GetExitValueByIndex(kwsysProcess* cp, int idx) |
739 | 0 | { |
740 | 0 | KWSYSPE_IDX_CHK(-1) |
741 | 0 | return cp->ProcessResults[idx].ExitValue; |
742 | 0 | } |
743 | | |
744 | | int kwsysProcess_GetExitCodeByIndex(kwsysProcess* cp, int idx) |
745 | 0 | { |
746 | 0 | KWSYSPE_IDX_CHK(-1) |
747 | 0 | return cp->CommandExitCodes[idx]; |
748 | 0 | } |
749 | | |
750 | | char const* kwsysProcess_GetExceptionStringByIndex(kwsysProcess* cp, int idx) |
751 | 0 | { |
752 | 0 | KWSYSPE_IDX_CHK("GetExceptionString called with NULL process management " |
753 | 0 | "structure or index out of bound") |
754 | 0 | if (cp->ProcessResults[idx].State == kwsysProcess_StateByIndex_Exception) { |
755 | 0 | return cp->ProcessResults[idx].ExitExceptionString; |
756 | 0 | } |
757 | 0 | return "No exception"; |
758 | 0 | } |
759 | | |
760 | | #undef KWSYSPE_IDX_CHK |
761 | | |
762 | | void kwsysProcess_Execute(kwsysProcess* cp) |
763 | 0 | { |
764 | 0 | int i; |
765 | | |
766 | | /* Do not execute a second copy simultaneously. */ |
767 | 0 | if (!cp || cp->State == kwsysProcess_State_Executing) { |
768 | 0 | return; |
769 | 0 | } |
770 | | |
771 | | /* Make sure we have something to run. */ |
772 | 0 | if (cp->NumberOfCommands < 1) { |
773 | 0 | strcpy(cp->ErrorMessage, "No command"); |
774 | 0 | cp->State = kwsysProcess_State_Error; |
775 | 0 | return; |
776 | 0 | } |
777 | | |
778 | | /* Initialize the control structure for a new process. */ |
779 | 0 | if (!kwsysProcessInitialize(cp)) { |
780 | 0 | strcpy(cp->ErrorMessage, "Out of memory"); |
781 | 0 | cp->State = kwsysProcess_State_Error; |
782 | 0 | return; |
783 | 0 | } |
784 | | |
785 | | #if defined(__VMS) |
786 | | /* Make sure pipes behave like streams on VMS. */ |
787 | | if (!kwsysProcessSetVMSFeature("DECC$STREAM_PIPE", 1)) { |
788 | | kwsysProcessCleanup(cp, 1); |
789 | | return; |
790 | | } |
791 | | #endif |
792 | | |
793 | | /* Save the real working directory of this process and change to |
794 | | the working directory for the child processes. This is needed |
795 | | to make pipe file paths evaluate correctly. */ |
796 | 0 | if (cp->WorkingDirectory) { |
797 | 0 | int r; |
798 | 0 | if (!getcwd(cp->RealWorkingDirectory, |
799 | 0 | (size_t)(cp->RealWorkingDirectoryLength))) { |
800 | 0 | kwsysProcessCleanup(cp, 1); |
801 | 0 | return; |
802 | 0 | } |
803 | | |
804 | | /* Some platforms specify that the chdir call may be |
805 | | interrupted. Repeat the call until it finishes. */ |
806 | 0 | while (((r = chdir(cp->WorkingDirectory)) < 0) && (errno == EINTR)) { |
807 | 0 | } |
808 | 0 | if (r < 0) { |
809 | 0 | kwsysProcessCleanup(cp, 1); |
810 | 0 | return; |
811 | 0 | } |
812 | 0 | } |
813 | | |
814 | | /* If not running a detached child, add this object to the global |
815 | | set of process objects that wish to be notified when a child |
816 | | exits. */ |
817 | 0 | if (!cp->OptionDetach) { |
818 | 0 | if (!kwsysProcessesAdd(cp)) { |
819 | 0 | kwsysProcessCleanup(cp, 1); |
820 | 0 | return; |
821 | 0 | } |
822 | 0 | } |
823 | | |
824 | | /* Setup the stdin pipe for the first process. */ |
825 | 0 | if (cp->PipeFileSTDIN) { |
826 | | /* Open a file for the child's stdin to read. */ |
827 | 0 | cp->PipeChildStd[0] = open(cp->PipeFileSTDIN, O_RDONLY); |
828 | 0 | if (cp->PipeChildStd[0] < 0) { |
829 | 0 | kwsysProcessCleanup(cp, 1); |
830 | 0 | return; |
831 | 0 | } |
832 | | |
833 | | /* Set close-on-exec flag on the pipe's end. */ |
834 | 0 | if (fcntl(cp->PipeChildStd[0], F_SETFD, FD_CLOEXEC) < 0) { |
835 | 0 | kwsysProcessCleanup(cp, 1); |
836 | 0 | return; |
837 | 0 | } |
838 | 0 | } else if (cp->PipeSharedSTDIN) { |
839 | 0 | cp->PipeChildStd[0] = 0; |
840 | 0 | } else if (cp->PipeNativeSTDIN[0] >= 0) { |
841 | 0 | cp->PipeChildStd[0] = cp->PipeNativeSTDIN[0]; |
842 | | |
843 | | /* Set close-on-exec flag on the pipe's ends. The read end will |
844 | | be dup2-ed into the stdin descriptor after the fork but before |
845 | | the exec. */ |
846 | 0 | if ((fcntl(cp->PipeNativeSTDIN[0], F_SETFD, FD_CLOEXEC) < 0) || |
847 | 0 | (fcntl(cp->PipeNativeSTDIN[1], F_SETFD, FD_CLOEXEC) < 0)) { |
848 | 0 | kwsysProcessCleanup(cp, 1); |
849 | 0 | return; |
850 | 0 | } |
851 | 0 | } else { |
852 | 0 | cp->PipeChildStd[0] = -1; |
853 | 0 | } |
854 | | |
855 | | /* Create the output pipe for the last process. |
856 | | We always create this so the pipe can be passed to select even if |
857 | | it will report closed immediately. */ |
858 | 0 | { |
859 | | /* Create the pipe. */ |
860 | 0 | int p[2]; |
861 | 0 | if (pipe(p KWSYSPE_VMS_NONBLOCK) < 0) { |
862 | 0 | kwsysProcessCleanup(cp, 1); |
863 | 0 | return; |
864 | 0 | } |
865 | | |
866 | | /* Store the pipe. */ |
867 | 0 | cp->PipeReadEnds[KWSYSPE_PIPE_STDOUT] = p[0]; |
868 | 0 | cp->PipeChildStd[1] = p[1]; |
869 | | |
870 | | /* Set close-on-exec flag on the pipe's ends. */ |
871 | 0 | if ((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || |
872 | 0 | (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) { |
873 | 0 | kwsysProcessCleanup(cp, 1); |
874 | 0 | return; |
875 | 0 | } |
876 | | |
877 | | /* Set to non-blocking in case select lies, or for the polling |
878 | | implementation. */ |
879 | 0 | if (!kwsysProcessSetNonBlocking(p[0])) { |
880 | 0 | kwsysProcessCleanup(cp, 1); |
881 | 0 | return; |
882 | 0 | } |
883 | 0 | } |
884 | | |
885 | 0 | if (cp->PipeFileSTDOUT) { |
886 | | /* Use a file for stdout. */ |
887 | 0 | if (!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1], |
888 | 0 | cp->PipeFileSTDOUT)) { |
889 | 0 | kwsysProcessCleanup(cp, 1); |
890 | 0 | return; |
891 | 0 | } |
892 | 0 | } else if (cp->PipeSharedSTDOUT) { |
893 | | /* Use the parent stdout. */ |
894 | 0 | kwsysProcessCleanupDescriptor(&cp->PipeChildStd[1]); |
895 | 0 | cp->PipeChildStd[1] = 1; |
896 | 0 | } else if (cp->PipeNativeSTDOUT[1] >= 0) { |
897 | | /* Use the given descriptor for stdout. */ |
898 | 0 | if (!kwsysProcessSetupOutputPipeNative(&cp->PipeChildStd[1], |
899 | 0 | cp->PipeNativeSTDOUT)) { |
900 | 0 | kwsysProcessCleanup(cp, 1); |
901 | 0 | return; |
902 | 0 | } |
903 | 0 | } |
904 | | |
905 | | /* Create stderr pipe to be shared by all processes in the pipeline. |
906 | | We always create this so the pipe can be passed to select even if |
907 | | it will report closed immediately. */ |
908 | 0 | { |
909 | | /* Create the pipe. */ |
910 | 0 | int p[2]; |
911 | 0 | if (pipe(p KWSYSPE_VMS_NONBLOCK) < 0) { |
912 | 0 | kwsysProcessCleanup(cp, 1); |
913 | 0 | return; |
914 | 0 | } |
915 | | |
916 | | /* Store the pipe. */ |
917 | 0 | cp->PipeReadEnds[KWSYSPE_PIPE_STDERR] = p[0]; |
918 | 0 | cp->PipeChildStd[2] = p[1]; |
919 | | |
920 | | /* Set close-on-exec flag on the pipe's ends. */ |
921 | 0 | if ((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || |
922 | 0 | (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) { |
923 | 0 | kwsysProcessCleanup(cp, 1); |
924 | 0 | return; |
925 | 0 | } |
926 | | |
927 | | /* Set to non-blocking in case select lies, or for the polling |
928 | | implementation. */ |
929 | 0 | if (!kwsysProcessSetNonBlocking(p[0])) { |
930 | 0 | kwsysProcessCleanup(cp, 1); |
931 | 0 | return; |
932 | 0 | } |
933 | 0 | } |
934 | | |
935 | 0 | if (cp->PipeFileSTDERR) { |
936 | | /* Use a file for stderr. */ |
937 | 0 | if (!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2], |
938 | 0 | cp->PipeFileSTDERR)) { |
939 | 0 | kwsysProcessCleanup(cp, 1); |
940 | 0 | return; |
941 | 0 | } |
942 | 0 | } else if (cp->PipeSharedSTDERR) { |
943 | | /* Use the parent stderr. */ |
944 | 0 | kwsysProcessCleanupDescriptor(&cp->PipeChildStd[2]); |
945 | 0 | cp->PipeChildStd[2] = 2; |
946 | 0 | } else if (cp->PipeNativeSTDERR[1] >= 0) { |
947 | | /* Use the given handle for stderr. */ |
948 | 0 | if (!kwsysProcessSetupOutputPipeNative(&cp->PipeChildStd[2], |
949 | 0 | cp->PipeNativeSTDERR)) { |
950 | 0 | kwsysProcessCleanup(cp, 1); |
951 | 0 | return; |
952 | 0 | } |
953 | 0 | } |
954 | | |
955 | | /* The timeout period starts now. */ |
956 | 0 | cp->StartTime = kwsysProcessTimeGetCurrent(); |
957 | 0 | cp->TimeoutTime.tv_sec = -1; |
958 | 0 | cp->TimeoutTime.tv_usec = -1; |
959 | | |
960 | | /* Create the pipeline of processes. */ |
961 | 0 | { |
962 | 0 | kwsysProcessCreateInformation si = { -1, -1, -1, { -1, -1 } }; |
963 | 0 | int nextStdIn = cp->PipeChildStd[0]; |
964 | 0 | for (i = 0; i < cp->NumberOfCommands; ++i) { |
965 | | /* Setup the process's pipes. */ |
966 | 0 | si.StdIn = nextStdIn; |
967 | 0 | if (i == cp->NumberOfCommands - 1) { |
968 | 0 | nextStdIn = -1; |
969 | 0 | si.StdOut = cp->PipeChildStd[1]; |
970 | 0 | } else { |
971 | | /* Create a pipe to sit between the children. */ |
972 | 0 | int p[2] = { -1, -1 }; |
973 | 0 | if (pipe(p KWSYSPE_VMS_NONBLOCK) < 0) { |
974 | 0 | if (nextStdIn != cp->PipeChildStd[0]) { |
975 | 0 | kwsysProcessCleanupDescriptor(&nextStdIn); |
976 | 0 | } |
977 | 0 | kwsysProcessCleanup(cp, 1); |
978 | 0 | return; |
979 | 0 | } |
980 | | |
981 | | /* Set close-on-exec flag on the pipe's ends. */ |
982 | 0 | if ((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || |
983 | 0 | (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) { |
984 | 0 | close(p[0]); |
985 | 0 | close(p[1]); |
986 | 0 | if (nextStdIn != cp->PipeChildStd[0]) { |
987 | 0 | kwsysProcessCleanupDescriptor(&nextStdIn); |
988 | 0 | } |
989 | 0 | kwsysProcessCleanup(cp, 1); |
990 | 0 | return; |
991 | 0 | } |
992 | 0 | nextStdIn = p[0]; |
993 | 0 | si.StdOut = p[1]; |
994 | 0 | } |
995 | 0 | si.StdErr = cp->MergeOutput ? cp->PipeChildStd[1] : cp->PipeChildStd[2]; |
996 | |
|
997 | 0 | { |
998 | 0 | int res = kwsysProcessCreate(cp, i, &si); |
999 | | |
1000 | | /* Close our copies of pipes used between children. */ |
1001 | 0 | if (si.StdIn != cp->PipeChildStd[0]) { |
1002 | 0 | kwsysProcessCleanupDescriptor(&si.StdIn); |
1003 | 0 | } |
1004 | 0 | if (si.StdOut != cp->PipeChildStd[1]) { |
1005 | 0 | kwsysProcessCleanupDescriptor(&si.StdOut); |
1006 | 0 | } |
1007 | 0 | if (si.StdErr != cp->PipeChildStd[2] && !cp->MergeOutput) { |
1008 | 0 | kwsysProcessCleanupDescriptor(&si.StdErr); |
1009 | 0 | } |
1010 | |
|
1011 | 0 | if (!res) { |
1012 | 0 | kwsysProcessCleanupDescriptor(&si.ErrorPipe[0]); |
1013 | 0 | kwsysProcessCleanupDescriptor(&si.ErrorPipe[1]); |
1014 | 0 | if (nextStdIn != cp->PipeChildStd[0]) { |
1015 | 0 | kwsysProcessCleanupDescriptor(&nextStdIn); |
1016 | 0 | } |
1017 | 0 | kwsysProcessCleanup(cp, 1); |
1018 | 0 | return; |
1019 | 0 | } |
1020 | 0 | } |
1021 | 0 | } |
1022 | 0 | } |
1023 | | |
1024 | | /* The parent process does not need the child's pipe ends. */ |
1025 | 0 | for (i = 0; i < 3; ++i) { |
1026 | 0 | kwsysProcessCleanupDescriptor(&cp->PipeChildStd[i]); |
1027 | 0 | } |
1028 | | |
1029 | | /* Restore the working directory. */ |
1030 | 0 | if (cp->RealWorkingDirectory) { |
1031 | | /* Some platforms specify that the chdir call may be |
1032 | | interrupted. Repeat the call until it finishes. */ |
1033 | 0 | while ((chdir(cp->RealWorkingDirectory) < 0) && (errno == EINTR)) { |
1034 | 0 | } |
1035 | 0 | free(cp->RealWorkingDirectory); |
1036 | 0 | cp->RealWorkingDirectory = 0; |
1037 | 0 | } |
1038 | | |
1039 | | /* All the pipes are now open. */ |
1040 | 0 | cp->PipesLeft = KWSYSPE_PIPE_COUNT; |
1041 | | |
1042 | | /* The process has now started. */ |
1043 | 0 | cp->State = kwsysProcess_State_Executing; |
1044 | 0 | cp->Detached = cp->OptionDetach; |
1045 | 0 | } |
1046 | | |
1047 | | kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp) |
1048 | 0 | { |
1049 | | /* Make sure a detached child process is running. */ |
1050 | 0 | if (!cp || !cp->Detached || cp->State != kwsysProcess_State_Executing || |
1051 | 0 | cp->TimeoutExpired || cp->Killed) { |
1052 | 0 | return; |
1053 | 0 | } |
1054 | | |
1055 | | /* Close all the pipes safely. */ |
1056 | 0 | kwsysProcessClosePipes(cp); |
1057 | | |
1058 | | /* We will not wait for exit, so cleanup now. */ |
1059 | 0 | kwsysProcessCleanup(cp, 0); |
1060 | | |
1061 | | /* The process has been disowned. */ |
1062 | 0 | cp->State = kwsysProcess_State_Disowned; |
1063 | 0 | } |
1064 | | |
1065 | | typedef struct kwsysProcessWaitData_s |
1066 | | { |
1067 | | int Expired; |
1068 | | int PipeId; |
1069 | | int User; |
1070 | | double* UserTimeout; |
1071 | | kwsysProcessTime TimeoutTime; |
1072 | | } kwsysProcessWaitData; |
1073 | | static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length, |
1074 | | kwsysProcessWaitData* wd); |
1075 | | |
1076 | | int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length, |
1077 | | double* userTimeout) |
1078 | 0 | { |
1079 | 0 | kwsysProcessTime userStartTime = { 0, 0 }; |
1080 | 0 | kwsysProcessWaitData wd = { 0, kwsysProcess_Pipe_None, 0, 0, { 0, 0 } }; |
1081 | 0 | wd.UserTimeout = userTimeout; |
1082 | | /* Make sure we are executing a process. */ |
1083 | 0 | if (!cp || cp->State != kwsysProcess_State_Executing || cp->Killed || |
1084 | 0 | cp->TimeoutExpired) { |
1085 | 0 | return kwsysProcess_Pipe_None; |
1086 | 0 | } |
1087 | | |
1088 | | /* Record the time at which user timeout period starts. */ |
1089 | 0 | if (userTimeout) { |
1090 | 0 | userStartTime = kwsysProcessTimeGetCurrent(); |
1091 | 0 | } |
1092 | | |
1093 | | /* Calculate the time at which a timeout will expire, and whether it |
1094 | | is the user or process timeout. */ |
1095 | 0 | wd.User = kwsysProcessGetTimeoutTime(cp, userTimeout, &wd.TimeoutTime); |
1096 | | |
1097 | | /* Data can only be available when pipes are open. If the process |
1098 | | is not running, cp->PipesLeft will be 0. */ |
1099 | 0 | while (cp->PipesLeft > 0 && |
1100 | 0 | !kwsysProcessWaitForPipe(cp, data, length, &wd)) { |
1101 | 0 | } |
1102 | | |
1103 | | /* Update the user timeout. */ |
1104 | 0 | if (userTimeout) { |
1105 | 0 | kwsysProcessTime userEndTime = kwsysProcessTimeGetCurrent(); |
1106 | 0 | kwsysProcessTime difference = |
1107 | 0 | kwsysProcessTimeSubtract(userEndTime, userStartTime); |
1108 | 0 | double d = kwsysProcessTimeToDouble(difference); |
1109 | 0 | *userTimeout -= d; |
1110 | 0 | if (*userTimeout < 0) { |
1111 | 0 | *userTimeout = 0; |
1112 | 0 | } |
1113 | 0 | } |
1114 | | |
1115 | | /* Check what happened. */ |
1116 | 0 | if (wd.PipeId) { |
1117 | | /* Data are ready on a pipe. */ |
1118 | 0 | return wd.PipeId; |
1119 | 0 | } |
1120 | 0 | if (wd.Expired) { |
1121 | | /* A timeout has expired. */ |
1122 | 0 | if (wd.User) { |
1123 | | /* The user timeout has expired. It has no time left. */ |
1124 | 0 | return kwsysProcess_Pipe_Timeout; |
1125 | 0 | } |
1126 | | |
1127 | | /* The process timeout has expired. Kill the children now. */ |
1128 | 0 | kwsysProcess_Kill(cp); |
1129 | 0 | cp->Killed = 0; |
1130 | 0 | cp->TimeoutExpired = 1; |
1131 | 0 | return kwsysProcess_Pipe_None; |
1132 | 0 | } |
1133 | | /* No pipes are left open. */ |
1134 | 0 | return kwsysProcess_Pipe_None; |
1135 | 0 | } |
1136 | | |
1137 | | static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length, |
1138 | | kwsysProcessWaitData* wd) |
1139 | 0 | { |
1140 | 0 | int i; |
1141 | 0 | kwsysProcessTimeNative timeoutLength; |
1142 | |
|
1143 | 0 | #if KWSYSPE_USE_SELECT |
1144 | 0 | int numReady = 0; |
1145 | 0 | int max = -1; |
1146 | 0 | kwsysProcessTimeNative* timeout = 0; |
1147 | | |
1148 | | /* Check for any open pipes with data reported ready by the last |
1149 | | call to select. According to "man select_tut" we must deal |
1150 | | with all descriptors reported by a call to select before |
1151 | | passing them to another select call. */ |
1152 | 0 | for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) { |
1153 | 0 | if (cp->PipeReadEnds[i] >= 0 && |
1154 | 0 | FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet)) { |
1155 | 0 | kwsysProcess_ssize_t n; |
1156 | | |
1157 | | /* We are handling this pipe now. Remove it from the set. */ |
1158 | 0 | FD_CLR(cp->PipeReadEnds[i], &cp->PipeSet); |
1159 | | |
1160 | | /* The pipe is ready to read without blocking. Keep trying to |
1161 | | read until the operation is not interrupted. */ |
1162 | 0 | while (((n = read(cp->PipeReadEnds[i], cp->PipeBuffer, |
1163 | 0 | KWSYSPE_PIPE_BUFFER_SIZE)) < 0) && |
1164 | 0 | (errno == EINTR)) { |
1165 | 0 | } |
1166 | 0 | if (n > 0) { |
1167 | | /* We have data on this pipe. */ |
1168 | 0 | if (i == KWSYSPE_PIPE_SIGNAL) { |
1169 | | /* A child process has terminated. */ |
1170 | 0 | kwsysProcessDestroy(cp); |
1171 | 0 | } else if (data && length) { |
1172 | | /* Report this data. */ |
1173 | 0 | *data = cp->PipeBuffer; |
1174 | 0 | *length = (int)(n); |
1175 | 0 | switch (i) { |
1176 | 0 | case KWSYSPE_PIPE_STDOUT: |
1177 | 0 | wd->PipeId = kwsysProcess_Pipe_STDOUT; |
1178 | 0 | break; |
1179 | 0 | case KWSYSPE_PIPE_STDERR: |
1180 | 0 | wd->PipeId = kwsysProcess_Pipe_STDERR; |
1181 | 0 | break; |
1182 | 0 | default: |
1183 | 0 | break; |
1184 | 0 | } |
1185 | 0 | return 1; |
1186 | 0 | } |
1187 | 0 | } else if (n < 0 && errno == EAGAIN) { |
1188 | | /* No data are really ready. The select call lied. See the |
1189 | | "man select" page on Linux for cases when this occurs. */ |
1190 | 0 | } else { |
1191 | | /* We are done reading from this pipe. */ |
1192 | 0 | kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); |
1193 | 0 | --cp->PipesLeft; |
1194 | 0 | } |
1195 | 0 | } |
1196 | 0 | } |
1197 | | |
1198 | | /* If we have data, break early. */ |
1199 | 0 | if (wd->PipeId) { |
1200 | 0 | return 1; |
1201 | 0 | } |
1202 | | |
1203 | | /* Make sure the set is empty (it should always be empty here |
1204 | | anyway). */ |
1205 | 0 | FD_ZERO(&cp->PipeSet); // NOLINT(readability-isolate-declaration) |
1206 | | |
1207 | | /* Setup a timeout if required. */ |
1208 | 0 | if (wd->TimeoutTime.tv_sec < 0) { |
1209 | 0 | timeout = 0; |
1210 | 0 | } else { |
1211 | 0 | timeout = &timeoutLength; |
1212 | 0 | } |
1213 | 0 | if (kwsysProcessGetTimeoutLeft( |
1214 | 0 | &wd->TimeoutTime, wd->User ? wd->UserTimeout : 0, &timeoutLength, 0)) { |
1215 | | /* Timeout has already expired. */ |
1216 | 0 | wd->Expired = 1; |
1217 | 0 | return 1; |
1218 | 0 | } |
1219 | | |
1220 | | /* Add the pipe reading ends that are still open. */ |
1221 | 0 | max = -1; |
1222 | 0 | for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) { |
1223 | 0 | if (cp->PipeReadEnds[i] >= 0) { |
1224 | 0 | FD_SET(cp->PipeReadEnds[i], &cp->PipeSet); |
1225 | 0 | if (cp->PipeReadEnds[i] > max) { |
1226 | 0 | max = cp->PipeReadEnds[i]; |
1227 | 0 | } |
1228 | 0 | } |
1229 | 0 | } |
1230 | | |
1231 | | /* Make sure we have a non-empty set. */ |
1232 | 0 | if (max < 0) { |
1233 | | /* All pipes have closed. Child has terminated. */ |
1234 | 0 | return 1; |
1235 | 0 | } |
1236 | | |
1237 | | /* Run select to block until data are available. Repeat call |
1238 | | until it is not interrupted. */ |
1239 | 0 | while (((numReady = select(max + 1, &cp->PipeSet, 0, 0, timeout)) < 0) && |
1240 | 0 | (errno == EINTR)) { |
1241 | 0 | } |
1242 | | |
1243 | | /* Check result of select. */ |
1244 | 0 | if (numReady == 0) { |
1245 | | /* Select's timeout expired. */ |
1246 | 0 | wd->Expired = 1; |
1247 | 0 | return 1; |
1248 | 0 | } |
1249 | 0 | if (numReady < 0) { |
1250 | | /* Select returned an error. Leave the error description in the |
1251 | | pipe buffer. */ |
1252 | 0 | strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); |
1253 | | |
1254 | | /* Kill the children now. */ |
1255 | 0 | kwsysProcess_Kill(cp); |
1256 | 0 | cp->Killed = 0; |
1257 | 0 | cp->SelectError = 1; |
1258 | 0 | } |
1259 | |
|
1260 | 0 | return 0; |
1261 | | #else |
1262 | | /* Poll pipes for data since we do not have select. */ |
1263 | | for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) { |
1264 | | if (cp->PipeReadEnds[i] >= 0) { |
1265 | | int const fd = cp->PipeReadEnds[i]; |
1266 | | int n = read(fd, cp->PipeBuffer, KWSYSPE_PIPE_BUFFER_SIZE); |
1267 | | if (n > 0) { |
1268 | | /* We have data on this pipe. */ |
1269 | | if (i == KWSYSPE_PIPE_SIGNAL) { |
1270 | | /* A child process has terminated. */ |
1271 | | kwsysProcessDestroy(cp); |
1272 | | } else if (data && length) { |
1273 | | /* Report this data. */ |
1274 | | *data = cp->PipeBuffer; |
1275 | | *length = n; |
1276 | | switch (i) { |
1277 | | case KWSYSPE_PIPE_STDOUT: |
1278 | | wd->PipeId = kwsysProcess_Pipe_STDOUT; |
1279 | | break; |
1280 | | case KWSYSPE_PIPE_STDERR: |
1281 | | wd->PipeId = kwsysProcess_Pipe_STDERR; |
1282 | | break; |
1283 | | }; |
1284 | | } |
1285 | | return 1; |
1286 | | } else if (n == 0) /* EOF */ |
1287 | | { |
1288 | | /* We are done reading from this pipe. */ |
1289 | | # if defined(__VMS) |
1290 | | if (!cp->CommandsLeft) |
1291 | | # endif |
1292 | | { |
1293 | | kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); |
1294 | | --cp->PipesLeft; |
1295 | | } |
1296 | | } else if (n < 0) /* error */ |
1297 | | { |
1298 | | # if defined(__VMS) |
1299 | | if (!cp->CommandsLeft) { |
1300 | | kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); |
1301 | | --cp->PipesLeft; |
1302 | | } else |
1303 | | # endif |
1304 | | if ((errno != EINTR) && (errno != EAGAIN)) { |
1305 | | strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); |
1306 | | /* Kill the children now. */ |
1307 | | kwsysProcess_Kill(cp); |
1308 | | cp->Killed = 0; |
1309 | | cp->SelectError = 1; |
1310 | | return 1; |
1311 | | } |
1312 | | } |
1313 | | } |
1314 | | } |
1315 | | |
1316 | | /* If we have data, break early. */ |
1317 | | if (wd->PipeId) { |
1318 | | return 1; |
1319 | | } |
1320 | | |
1321 | | if (kwsysProcessGetTimeoutLeft( |
1322 | | &wd->TimeoutTime, wd->User ? wd->UserTimeout : 0, &timeoutLength, 1)) { |
1323 | | /* Timeout has already expired. */ |
1324 | | wd->Expired = 1; |
1325 | | return 1; |
1326 | | } |
1327 | | |
1328 | | /* Sleep a little, try again. */ |
1329 | | { |
1330 | | unsigned int msec = |
1331 | | ((timeoutLength.tv_sec * 1000) + (timeoutLength.tv_usec / 1000)); |
1332 | | if (msec > 100000) { |
1333 | | msec = 100000; /* do not sleep more than 100 milliseconds at a time */ |
1334 | | } |
1335 | | kwsysProcess_usleep(msec); |
1336 | | } |
1337 | | return 0; |
1338 | | #endif |
1339 | 0 | } |
1340 | | |
1341 | | int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout) |
1342 | 0 | { |
1343 | 0 | int prPipe = 0; |
1344 | | |
1345 | | /* Make sure we are executing a process. */ |
1346 | 0 | if (!cp || cp->State != kwsysProcess_State_Executing) { |
1347 | 0 | return 1; |
1348 | 0 | } |
1349 | | |
1350 | | /* Wait for all the pipes to close. Ignore all data. */ |
1351 | 0 | while ((prPipe = kwsysProcess_WaitForData(cp, 0, 0, userTimeout)) > 0) { |
1352 | 0 | if (prPipe == kwsysProcess_Pipe_Timeout) { |
1353 | 0 | return 0; |
1354 | 0 | } |
1355 | 0 | } |
1356 | | |
1357 | | /* Check if there was an error in one of the waitpid calls. */ |
1358 | 0 | if (cp->State == kwsysProcess_State_Error) { |
1359 | | /* The error message is already in its buffer. Tell |
1360 | | kwsysProcessCleanup to not create it. */ |
1361 | 0 | kwsysProcessCleanup(cp, 0); |
1362 | 0 | return 1; |
1363 | 0 | } |
1364 | | |
1365 | | /* Check whether the child reported an error invoking the process. */ |
1366 | 0 | if (cp->SelectError) { |
1367 | | /* The error message is already in its buffer. Tell |
1368 | | kwsysProcessCleanup to not create it. */ |
1369 | 0 | kwsysProcessCleanup(cp, 0); |
1370 | 0 | cp->State = kwsysProcess_State_Error; |
1371 | 0 | return 1; |
1372 | 0 | } |
1373 | | /* Determine the outcome. */ |
1374 | 0 | if (cp->Killed) { |
1375 | | /* We killed the child. */ |
1376 | 0 | cp->State = kwsysProcess_State_Killed; |
1377 | 0 | } else if (cp->TimeoutExpired) { |
1378 | | /* The timeout expired. */ |
1379 | 0 | cp->State = kwsysProcess_State_Expired; |
1380 | 0 | } else { |
1381 | | /* The children exited. Report the outcome of the child processes. */ |
1382 | 0 | for (prPipe = 0; prPipe < cp->NumberOfCommands; ++prPipe) { |
1383 | 0 | cp->ProcessResults[prPipe].ExitCode = cp->CommandExitCodes[prPipe]; |
1384 | 0 | if (WIFEXITED(cp->ProcessResults[prPipe].ExitCode)) { |
1385 | | /* The child exited normally. */ |
1386 | 0 | cp->ProcessResults[prPipe].State = kwsysProcess_StateByIndex_Exited; |
1387 | 0 | cp->ProcessResults[prPipe].ExitException = kwsysProcess_Exception_None; |
1388 | 0 | cp->ProcessResults[prPipe].ExitValue = |
1389 | | // NOLINTNEXTLINE(google-readability-casting) |
1390 | 0 | (int)WEXITSTATUS(cp->ProcessResults[prPipe].ExitCode); |
1391 | 0 | } else if (WIFSIGNALED(cp->ProcessResults[prPipe].ExitCode)) { |
1392 | | /* The child received an unhandled signal. */ |
1393 | 0 | cp->ProcessResults[prPipe].State = kwsysProcess_State_Exception; |
1394 | 0 | kwsysProcessSetExitExceptionByIndex( |
1395 | | // NOLINTNEXTLINE(google-readability-casting) |
1396 | 0 | cp, (int)WTERMSIG(cp->ProcessResults[prPipe].ExitCode), prPipe); |
1397 | 0 | } else { |
1398 | | /* Error getting the child return code. */ |
1399 | 0 | strcpy(cp->ProcessResults[prPipe].ExitExceptionString, |
1400 | 0 | "Error getting child return code."); |
1401 | 0 | cp->ProcessResults[prPipe].State = kwsysProcess_StateByIndex_Error; |
1402 | 0 | } |
1403 | 0 | } |
1404 | | /* support legacy state status value */ |
1405 | 0 | cp->State = cp->ProcessResults[cp->NumberOfCommands - 1].State; |
1406 | 0 | } |
1407 | | /* Normal cleanup. */ |
1408 | 0 | kwsysProcessCleanup(cp, 0); |
1409 | 0 | return 1; |
1410 | 0 | } |
1411 | | |
1412 | | void kwsysProcess_Interrupt(kwsysProcess* cp) |
1413 | 0 | { |
1414 | 0 | int i; |
1415 | | /* Make sure we are executing a process. */ |
1416 | 0 | if (!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired || |
1417 | 0 | cp->Killed) { |
1418 | 0 | return; |
1419 | 0 | } |
1420 | | |
1421 | | /* Interrupt the children. */ |
1422 | 0 | if (cp->CreateProcessGroup) { |
1423 | 0 | if (cp->ForkPIDs) { |
1424 | 0 | for (i = 0; i < cp->NumberOfCommands; ++i) { |
1425 | | /* Make sure the PID is still valid. */ |
1426 | 0 | if (cp->ForkPIDs[i]) { |
1427 | | /* The user created a process group for this process. The group ID |
1428 | | is the process ID for the original process in the group. */ |
1429 | 0 | kill(-cp->ForkPIDs[i], SIGINT); |
1430 | 0 | } |
1431 | 0 | } |
1432 | 0 | } |
1433 | 0 | } else { |
1434 | | /* No process group was created. Kill our own process group. |
1435 | | NOTE: While one could argue that we could call kill(cp->ForkPIDs[i], |
1436 | | SIGINT) as a way to still interrupt the process even though it's not in |
1437 | | a special group, this is not an option on Windows. Therefore, we kill |
1438 | | the current process group for consistency with Windows. */ |
1439 | 0 | kill(0, SIGINT); |
1440 | 0 | } |
1441 | 0 | } |
1442 | | |
1443 | | void kwsysProcess_Kill(kwsysProcess* cp) |
1444 | 0 | { |
1445 | 0 | int i; |
1446 | | |
1447 | | /* Make sure we are executing a process. */ |
1448 | 0 | if (!cp || cp->State != kwsysProcess_State_Executing) { |
1449 | 0 | return; |
1450 | 0 | } |
1451 | | |
1452 | | /* First close the child exit report pipe write end to avoid causing a |
1453 | | SIGPIPE when the child terminates and our signal handler tries to |
1454 | | report it after we have already closed the read end. */ |
1455 | 0 | kwsysProcessCleanupDescriptor(&cp->SignalPipe); |
1456 | |
|
1457 | 0 | #if !defined(__APPLE__) |
1458 | | /* Close all the pipe read ends. Do this before killing the |
1459 | | children because Cygwin has problems killing processes that are |
1460 | | blocking to wait for writing to their output pipes. */ |
1461 | 0 | kwsysProcessClosePipes(cp); |
1462 | 0 | #endif |
1463 | | |
1464 | | /* Kill the children. */ |
1465 | 0 | cp->Killed = 1; |
1466 | 0 | for (i = 0; i < cp->NumberOfCommands; ++i) { |
1467 | 0 | int status; |
1468 | 0 | if (cp->ForkPIDs[i]) { |
1469 | | /* Kill the child. */ |
1470 | 0 | kwsysProcessKill(cp->ForkPIDs[i]); |
1471 | | |
1472 | | /* Reap the child. Keep trying until the call is not |
1473 | | interrupted. */ |
1474 | 0 | while ((waitpid(cp->ForkPIDs[i], &status, 0) < 0) && (errno == EINTR)) { |
1475 | 0 | } |
1476 | 0 | } |
1477 | 0 | } |
1478 | |
|
1479 | | #if defined(__APPLE__) |
1480 | | /* Close all the pipe read ends. Do this after killing the |
1481 | | children because OS X has problems closing pipe read ends whose |
1482 | | pipes are full and still have an open write end. */ |
1483 | | kwsysProcessClosePipes(cp); |
1484 | | #endif |
1485 | |
|
1486 | 0 | cp->CommandsLeft = 0; |
1487 | 0 | } |
1488 | | |
1489 | | /* Call the free() function with a pointer to volatile without causing |
1490 | | compiler warnings. */ |
1491 | | static void kwsysProcessVolatileFree(void volatile* p) |
1492 | 0 | { |
1493 | | /* clang has made it impossible to free memory that points to volatile |
1494 | | without first using special pragmas to disable a warning... */ |
1495 | 0 | #if defined(__clang__) && !defined(__INTEL_COMPILER) |
1496 | 0 | # pragma clang diagnostic push |
1497 | 0 | # pragma clang diagnostic ignored "-Wcast-qual" |
1498 | 0 | #endif |
1499 | 0 | free((void*)p); /* The cast will silence most compilers, but not clang. */ |
1500 | 0 | #if defined(__clang__) && !defined(__INTEL_COMPILER) |
1501 | 0 | # pragma clang diagnostic pop |
1502 | 0 | #endif |
1503 | 0 | } |
1504 | | |
1505 | | /* Initialize a process control structure for kwsysProcess_Execute. */ |
1506 | | static int kwsysProcessInitialize(kwsysProcess* cp) |
1507 | 0 | { |
1508 | 0 | int i; |
1509 | 0 | pid_t volatile* oldForkPIDs; |
1510 | 0 | for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) { |
1511 | 0 | cp->PipeReadEnds[i] = -1; |
1512 | 0 | } |
1513 | 0 | for (i = 0; i < 3; ++i) { |
1514 | 0 | cp->PipeChildStd[i] = -1; |
1515 | 0 | } |
1516 | 0 | cp->SignalPipe = -1; |
1517 | 0 | cp->SelectError = 0; |
1518 | 0 | cp->StartTime.tv_sec = -1; |
1519 | 0 | cp->StartTime.tv_usec = -1; |
1520 | 0 | cp->TimeoutTime.tv_sec = -1; |
1521 | 0 | cp->TimeoutTime.tv_usec = -1; |
1522 | 0 | cp->TimeoutExpired = 0; |
1523 | 0 | cp->PipesLeft = 0; |
1524 | 0 | cp->CommandsLeft = 0; |
1525 | 0 | #if KWSYSPE_USE_SELECT |
1526 | 0 | FD_ZERO(&cp->PipeSet); // NOLINT(readability-isolate-declaration) |
1527 | 0 | #endif |
1528 | 0 | cp->State = kwsysProcess_State_Starting; |
1529 | 0 | cp->Killed = 0; |
1530 | 0 | cp->ErrorMessage[0] = 0; |
1531 | |
|
1532 | 0 | oldForkPIDs = cp->ForkPIDs; |
1533 | 0 | cp->ForkPIDs = (pid_t volatile*)malloc(sizeof(pid_t volatile) * |
1534 | 0 | (size_t)(cp->NumberOfCommands)); |
1535 | 0 | kwsysProcessVolatileFree(oldForkPIDs); |
1536 | 0 | if (!cp->ForkPIDs) { |
1537 | 0 | return 0; |
1538 | 0 | } |
1539 | 0 | for (i = 0; i < cp->NumberOfCommands; ++i) { |
1540 | 0 | cp->ForkPIDs[i] = 0; /* can't use memset due to volatile */ |
1541 | 0 | } |
1542 | |
|
1543 | 0 | free(cp->CommandExitCodes); |
1544 | 0 | cp->CommandExitCodes = |
1545 | 0 | (int*)malloc(sizeof(int) * (size_t)(cp->NumberOfCommands)); |
1546 | 0 | if (!cp->CommandExitCodes) { |
1547 | 0 | return 0; |
1548 | 0 | } |
1549 | 0 | memset(cp->CommandExitCodes, 0, |
1550 | 0 | sizeof(int) * (size_t)(cp->NumberOfCommands)); |
1551 | | |
1552 | | /* Allocate process result information for each process. */ |
1553 | 0 | free(cp->ProcessResults); |
1554 | 0 | cp->ProcessResults = (kwsysProcessResults*)malloc( |
1555 | 0 | sizeof(kwsysProcessResults) * (size_t)(cp->NumberOfCommands)); |
1556 | 0 | if (!cp->ProcessResults) { |
1557 | 0 | return 0; |
1558 | 0 | } |
1559 | 0 | memset(cp->ProcessResults, 0, |
1560 | 0 | sizeof(kwsysProcessResults) * (size_t)(cp->NumberOfCommands)); |
1561 | 0 | for (i = 0; i < cp->NumberOfCommands; i++) { |
1562 | 0 | cp->ProcessResults[i].ExitException = kwsysProcess_Exception_None; |
1563 | 0 | cp->ProcessResults[i].State = kwsysProcess_StateByIndex_Starting; |
1564 | 0 | cp->ProcessResults[i].ExitCode = 1; |
1565 | 0 | cp->ProcessResults[i].ExitValue = 1; |
1566 | 0 | strcpy(cp->ProcessResults[i].ExitExceptionString, "No exception"); |
1567 | 0 | } |
1568 | | |
1569 | | /* Allocate memory to save the real working directory. */ |
1570 | 0 | if (cp->WorkingDirectory) { |
1571 | | #if defined(MAXPATHLEN) |
1572 | | cp->RealWorkingDirectoryLength = MAXPATHLEN; |
1573 | | #elif defined(PATH_MAX) |
1574 | | cp->RealWorkingDirectoryLength = PATH_MAX; |
1575 | | #else |
1576 | 0 | cp->RealWorkingDirectoryLength = 4096; |
1577 | 0 | #endif |
1578 | 0 | cp->RealWorkingDirectory = |
1579 | 0 | (char*)malloc((size_t)(cp->RealWorkingDirectoryLength)); |
1580 | 0 | if (!cp->RealWorkingDirectory) { |
1581 | 0 | return 0; |
1582 | 0 | } |
1583 | 0 | } |
1584 | | |
1585 | 0 | return 1; |
1586 | 0 | } |
1587 | | |
1588 | | /* Free all resources used by the given kwsysProcess instance that were |
1589 | | allocated by kwsysProcess_Execute. */ |
1590 | | static void kwsysProcessCleanup(kwsysProcess* cp, int error) |
1591 | 0 | { |
1592 | 0 | int i; |
1593 | |
|
1594 | 0 | if (error) { |
1595 | | /* We are cleaning up due to an error. Report the error message |
1596 | | if one has not been provided already. */ |
1597 | 0 | if (cp->ErrorMessage[0] == 0) { |
1598 | 0 | strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); |
1599 | 0 | } |
1600 | | |
1601 | | /* Set the error state. */ |
1602 | 0 | cp->State = kwsysProcess_State_Error; |
1603 | | |
1604 | | /* Kill any children already started. */ |
1605 | 0 | if (cp->ForkPIDs) { |
1606 | 0 | int status; |
1607 | 0 | for (i = 0; i < cp->NumberOfCommands; ++i) { |
1608 | 0 | if (cp->ForkPIDs[i]) { |
1609 | | /* Kill the child. */ |
1610 | 0 | kwsysProcessKill(cp->ForkPIDs[i]); |
1611 | | |
1612 | | /* Reap the child. Keep trying until the call is not |
1613 | | interrupted. */ |
1614 | 0 | while ((waitpid(cp->ForkPIDs[i], &status, 0) < 0) && |
1615 | 0 | (errno == EINTR)) { |
1616 | 0 | } |
1617 | 0 | } |
1618 | 0 | } |
1619 | 0 | } |
1620 | | |
1621 | | /* Restore the working directory. */ |
1622 | 0 | if (cp->RealWorkingDirectory) { |
1623 | 0 | while ((chdir(cp->RealWorkingDirectory) < 0) && (errno == EINTR)) { |
1624 | 0 | } |
1625 | 0 | } |
1626 | 0 | } |
1627 | | |
1628 | | /* If not creating a detached child, remove this object from the |
1629 | | global set of process objects that wish to be notified when a |
1630 | | child exits. */ |
1631 | 0 | if (!cp->OptionDetach) { |
1632 | 0 | kwsysProcessesRemove(cp); |
1633 | 0 | } |
1634 | | |
1635 | | /* Free memory. */ |
1636 | 0 | if (cp->ForkPIDs) { |
1637 | 0 | kwsysProcessVolatileFree(cp->ForkPIDs); |
1638 | 0 | cp->ForkPIDs = 0; |
1639 | 0 | } |
1640 | 0 | if (cp->RealWorkingDirectory) { |
1641 | 0 | free(cp->RealWorkingDirectory); |
1642 | 0 | cp->RealWorkingDirectory = 0; |
1643 | 0 | } |
1644 | | |
1645 | | /* Close pipe handles. */ |
1646 | 0 | for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) { |
1647 | 0 | kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); |
1648 | 0 | } |
1649 | 0 | for (i = 0; i < 3; ++i) { |
1650 | 0 | kwsysProcessCleanupDescriptor(&cp->PipeChildStd[i]); |
1651 | 0 | } |
1652 | 0 | } |
1653 | | |
1654 | | /* Close the given file descriptor if it is open. Reset its value to -1. */ |
1655 | | static void kwsysProcessCleanupDescriptor(int* pfd) |
1656 | 0 | { |
1657 | 0 | if (pfd && *pfd > 2) { |
1658 | | /* Keep trying to close until it is not interrupted by a |
1659 | | * signal. */ |
1660 | 0 | while ((close(*pfd) < 0) && (errno == EINTR)) { |
1661 | 0 | } |
1662 | 0 | *pfd = -1; |
1663 | 0 | } |
1664 | 0 | } |
1665 | | |
1666 | | static void kwsysProcessClosePipes(kwsysProcess* cp) |
1667 | 0 | { |
1668 | 0 | int i; |
1669 | | |
1670 | | /* Close any pipes that are still open. */ |
1671 | 0 | for (i = 0; i < KWSYSPE_PIPE_COUNT; ++i) { |
1672 | 0 | if (cp->PipeReadEnds[i] >= 0) { |
1673 | 0 | #if KWSYSPE_USE_SELECT |
1674 | | /* If the pipe was reported by the last call to select, we must |
1675 | | read from it. This is needed to satisfy the suggestions from |
1676 | | "man select_tut" and is not needed for the polling |
1677 | | implementation. Ignore the data. */ |
1678 | 0 | if (FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet)) { |
1679 | | /* We are handling this pipe now. Remove it from the set. */ |
1680 | 0 | FD_CLR(cp->PipeReadEnds[i], &cp->PipeSet); |
1681 | | |
1682 | | /* The pipe is ready to read without blocking. Keep trying to |
1683 | | read until the operation is not interrupted. */ |
1684 | 0 | while ((read(cp->PipeReadEnds[i], cp->PipeBuffer, |
1685 | 0 | KWSYSPE_PIPE_BUFFER_SIZE) < 0) && |
1686 | 0 | (errno == EINTR)) { |
1687 | 0 | } |
1688 | 0 | } |
1689 | 0 | #endif |
1690 | | |
1691 | | /* We are done reading from this pipe. */ |
1692 | 0 | kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); |
1693 | 0 | --cp->PipesLeft; |
1694 | 0 | } |
1695 | 0 | } |
1696 | 0 | } |
1697 | | |
1698 | | static int kwsysProcessSetNonBlocking(int fd) |
1699 | 0 | { |
1700 | 0 | int flags = fcntl(fd, F_GETFL); |
1701 | 0 | if (flags >= 0) { |
1702 | 0 | flags = fcntl(fd, F_SETFL, flags | O_NONBLOCK); |
1703 | 0 | } |
1704 | 0 | return flags >= 0; |
1705 | 0 | } |
1706 | | |
1707 | | #if defined(__VMS) |
1708 | | int decc$set_child_standard_streams(int fd1, int fd2, int fd3); |
1709 | | #endif |
1710 | | |
1711 | | static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, |
1712 | | kwsysProcessCreateInformation* si) |
1713 | 0 | { |
1714 | 0 | sigset_t mask; |
1715 | 0 | sigset_t old_mask; |
1716 | 0 | int pgidPipe[2]; |
1717 | 0 | char tmp; |
1718 | 0 | ssize_t readRes; |
1719 | | |
1720 | | /* Create the error reporting pipe. */ |
1721 | 0 | if (pipe(si->ErrorPipe) < 0) { |
1722 | 0 | return 0; |
1723 | 0 | } |
1724 | | |
1725 | | /* Create a pipe for detecting that the child process has created a process |
1726 | | group and session. */ |
1727 | 0 | if (pipe(pgidPipe) < 0) { |
1728 | 0 | kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); |
1729 | 0 | kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); |
1730 | 0 | return 0; |
1731 | 0 | } |
1732 | | |
1733 | | /* Set close-on-exec flag on the pipe's write end. */ |
1734 | 0 | if (fcntl(si->ErrorPipe[1], F_SETFD, FD_CLOEXEC) < 0 || |
1735 | 0 | fcntl(pgidPipe[1], F_SETFD, FD_CLOEXEC) < 0) { |
1736 | 0 | kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); |
1737 | 0 | kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); |
1738 | 0 | kwsysProcessCleanupDescriptor(&pgidPipe[0]); |
1739 | 0 | kwsysProcessCleanupDescriptor(&pgidPipe[1]); |
1740 | 0 | return 0; |
1741 | 0 | } |
1742 | | |
1743 | | /* Block SIGINT / SIGTERM while we start. The purpose is so that our signal |
1744 | | handler doesn't get called from the child process after the fork and |
1745 | | before the exec, and subsequently start kill()'ing PIDs from ForkPIDs. */ |
1746 | 0 | sigemptyset(&mask); |
1747 | 0 | sigaddset(&mask, SIGINT); |
1748 | 0 | sigaddset(&mask, SIGTERM); |
1749 | 0 | if (sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) { |
1750 | 0 | kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); |
1751 | 0 | kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); |
1752 | 0 | kwsysProcessCleanupDescriptor(&pgidPipe[0]); |
1753 | 0 | kwsysProcessCleanupDescriptor(&pgidPipe[1]); |
1754 | 0 | return 0; |
1755 | 0 | } |
1756 | | |
1757 | | /* Fork off a child process. */ |
1758 | | #if defined(__VMS) |
1759 | | /* VMS needs vfork and execvp to be in the same function because |
1760 | | they use setjmp/longjmp to run the child startup code in the |
1761 | | parent! TODO: OptionDetach. Also |
1762 | | TODO: CreateProcessGroup. */ |
1763 | | cp->ForkPIDs[prIndex] = vfork(); |
1764 | | #else |
1765 | 0 | cp->ForkPIDs[prIndex] = kwsysProcessFork(cp, si); |
1766 | 0 | #endif |
1767 | 0 | if (cp->ForkPIDs[prIndex] < 0) { |
1768 | 0 | sigprocmask(SIG_SETMASK, &old_mask, 0); |
1769 | 0 | kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); |
1770 | 0 | kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); |
1771 | 0 | kwsysProcessCleanupDescriptor(&pgidPipe[0]); |
1772 | 0 | kwsysProcessCleanupDescriptor(&pgidPipe[1]); |
1773 | 0 | return 0; |
1774 | 0 | } |
1775 | | |
1776 | 0 | if (cp->ForkPIDs[prIndex] == 0) { |
1777 | | #if defined(__VMS) |
1778 | | /* Specify standard pipes for child process. */ |
1779 | | decc$set_child_standard_streams(si->StdIn, si->StdOut, si->StdErr); |
1780 | | #else |
1781 | | /* Close the read end of the error reporting / process group |
1782 | | setup pipe. */ |
1783 | 0 | close(si->ErrorPipe[0]); |
1784 | 0 | close(pgidPipe[0]); |
1785 | | |
1786 | | /* Setup the stdin, stdout, and stderr pipes. */ |
1787 | 0 | if (si->StdIn > 0) { |
1788 | 0 | dup2(si->StdIn, 0); |
1789 | 0 | } else if (si->StdIn < 0) { |
1790 | 0 | close(0); |
1791 | 0 | } |
1792 | 0 | if (si->StdOut != 1) { |
1793 | 0 | dup2(si->StdOut, 1); |
1794 | 0 | } |
1795 | 0 | if (si->StdErr != 2) { |
1796 | 0 | dup2(si->StdErr, 2); |
1797 | 0 | } |
1798 | | |
1799 | | /* Clear the close-on-exec flag for stdin, stdout, and stderr. |
1800 | | All other pipe handles will be closed when exec succeeds. */ |
1801 | 0 | fcntl(0, F_SETFD, 0); |
1802 | 0 | fcntl(1, F_SETFD, 0); |
1803 | 0 | fcntl(2, F_SETFD, 0); |
1804 | | |
1805 | | /* Restore all default signal handlers. */ |
1806 | 0 | kwsysProcessRestoreDefaultSignalHandlers(); |
1807 | | |
1808 | | /* Now that we have restored default signal handling and created the |
1809 | | process group, restore mask. */ |
1810 | 0 | sigprocmask(SIG_SETMASK, &old_mask, 0); |
1811 | | |
1812 | | /* Create new process group. We use setsid instead of setpgid to avoid |
1813 | | the child getting hung up on signals like SIGTTOU. (In the real world, |
1814 | | this has been observed where "git svn" ends up calling the "resize" |
1815 | | program which opens /dev/tty. */ |
1816 | 0 | if (cp->CreateProcessGroup && setsid() < 0) { |
1817 | 0 | kwsysProcessChildErrorExit(si->ErrorPipe[1]); |
1818 | 0 | } |
1819 | 0 | #endif |
1820 | | |
1821 | | /* Execute the real process. If successful, this does not return. */ |
1822 | 0 | execvp(cp->Commands[prIndex][0], cp->Commands[prIndex]); |
1823 | | /* TODO: What does VMS do if the child fails to start? */ |
1824 | | /* TODO: On VMS, how do we put the process in a new group? */ |
1825 | | |
1826 | | /* Failure. Report error to parent and terminate. */ |
1827 | 0 | kwsysProcessChildErrorExit(si->ErrorPipe[1]); |
1828 | 0 | } |
1829 | |
|
1830 | | #if defined(__VMS) |
1831 | | /* Restore the standard pipes of this process. */ |
1832 | | decc$set_child_standard_streams(0, 1, 2); |
1833 | | #endif |
1834 | | |
1835 | | /* We are done with the error reporting pipe and process group setup pipe |
1836 | | write end. */ |
1837 | 0 | kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]); |
1838 | 0 | kwsysProcessCleanupDescriptor(&pgidPipe[1]); |
1839 | | |
1840 | | /* Make sure the child is in the process group before we proceed. This |
1841 | | avoids race conditions with calls to the kill function that we make for |
1842 | | signalling process groups. */ |
1843 | 0 | while ((readRes = read(pgidPipe[0], &tmp, 1)) > 0) { |
1844 | 0 | } |
1845 | 0 | if (readRes < 0) { |
1846 | 0 | sigprocmask(SIG_SETMASK, &old_mask, 0); |
1847 | 0 | kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); |
1848 | 0 | kwsysProcessCleanupDescriptor(&pgidPipe[0]); |
1849 | 0 | return 0; |
1850 | 0 | } |
1851 | 0 | kwsysProcessCleanupDescriptor(&pgidPipe[0]); |
1852 | | |
1853 | | /* Unmask signals. */ |
1854 | 0 | if (sigprocmask(SIG_SETMASK, &old_mask, 0) < 0) { |
1855 | 0 | kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); |
1856 | 0 | return 0; |
1857 | 0 | } |
1858 | | |
1859 | | /* A child has been created. */ |
1860 | 0 | ++cp->CommandsLeft; |
1861 | | |
1862 | | /* Block until the child's exec call succeeds and closes the error |
1863 | | pipe or writes data to the pipe to report an error. */ |
1864 | 0 | { |
1865 | 0 | kwsysProcess_ssize_t total = 0; |
1866 | 0 | kwsysProcess_ssize_t n = 1; |
1867 | | /* Read the entire error message up to the length of our buffer. */ |
1868 | 0 | while (total < KWSYSPE_PIPE_BUFFER_SIZE && n > 0) { |
1869 | | /* Keep trying to read until the operation is not interrupted. */ |
1870 | 0 | while (((n = read(si->ErrorPipe[0], cp->ErrorMessage + total, |
1871 | 0 | (size_t)(KWSYSPE_PIPE_BUFFER_SIZE - total))) < 0) && |
1872 | 0 | (errno == EINTR)) { |
1873 | 0 | } |
1874 | 0 | if (n > 0) { |
1875 | 0 | total += n; |
1876 | 0 | } |
1877 | 0 | } |
1878 | | |
1879 | | /* We are done with the error reporting pipe read end. */ |
1880 | 0 | kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]); |
1881 | |
|
1882 | 0 | if (total > 0) { |
1883 | | /* The child failed to execute the process. */ |
1884 | 0 | return 0; |
1885 | 0 | } |
1886 | 0 | } |
1887 | | |
1888 | 0 | return 1; |
1889 | 0 | } |
1890 | | |
1891 | | static void kwsysProcessDestroy(kwsysProcess* cp) |
1892 | 0 | { |
1893 | | /* A child process has terminated. Reap it if it is one handled by |
1894 | | this object. */ |
1895 | 0 | int i; |
1896 | | /* Temporarily disable signals that access ForkPIDs. We don't want them to |
1897 | | read a reaped PID, and writes to ForkPIDs are not atomic. */ |
1898 | 0 | sigset_t mask; |
1899 | 0 | sigset_t old_mask; |
1900 | 0 | sigemptyset(&mask); |
1901 | 0 | sigaddset(&mask, SIGINT); |
1902 | 0 | sigaddset(&mask, SIGTERM); |
1903 | 0 | if (sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) { |
1904 | 0 | return; |
1905 | 0 | } |
1906 | | |
1907 | 0 | for (i = 0; i < cp->NumberOfCommands; ++i) { |
1908 | 0 | if (cp->ForkPIDs[i]) { |
1909 | 0 | int result; |
1910 | 0 | while (((result = waitpid(cp->ForkPIDs[i], &cp->CommandExitCodes[i], |
1911 | 0 | WNOHANG)) < 0) && |
1912 | 0 | (errno == EINTR)) { |
1913 | 0 | } |
1914 | 0 | if (result > 0) { |
1915 | | /* This child has terminated. */ |
1916 | 0 | cp->ForkPIDs[i] = 0; |
1917 | 0 | if (--cp->CommandsLeft == 0) { |
1918 | | /* All children have terminated. Close the signal pipe |
1919 | | write end so that no more notifications are sent to this |
1920 | | object. */ |
1921 | 0 | kwsysProcessCleanupDescriptor(&cp->SignalPipe); |
1922 | | |
1923 | | /* TODO: Once the children have terminated, switch |
1924 | | WaitForData to use a non-blocking read to get the |
1925 | | rest of the data from the pipe. This is needed when |
1926 | | grandchildren keep the output pipes open. */ |
1927 | 0 | } |
1928 | 0 | } else if (result < 0 && cp->State != kwsysProcess_State_Error) { |
1929 | | /* Unexpected error. Report the first time this happens. */ |
1930 | 0 | strncpy(cp->ErrorMessage, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); |
1931 | 0 | cp->State = kwsysProcess_State_Error; |
1932 | 0 | } |
1933 | 0 | } |
1934 | 0 | } |
1935 | | |
1936 | | /* Re-enable signals. */ |
1937 | 0 | sigprocmask(SIG_SETMASK, &old_mask, 0); |
1938 | 0 | } |
1939 | | |
1940 | | static int kwsysProcessSetupOutputPipeFile(int* p, char const* name) |
1941 | 0 | { |
1942 | 0 | int fout; |
1943 | 0 | if (!name) { |
1944 | 0 | return 1; |
1945 | 0 | } |
1946 | | |
1947 | | /* Close the existing descriptor. */ |
1948 | 0 | kwsysProcessCleanupDescriptor(p); |
1949 | | |
1950 | | /* Open a file for the pipe to write. */ |
1951 | 0 | if ((fout = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { |
1952 | 0 | return 0; |
1953 | 0 | } |
1954 | | |
1955 | | /* Set close-on-exec flag on the pipe's end. */ |
1956 | 0 | if (fcntl(fout, F_SETFD, FD_CLOEXEC) < 0) { |
1957 | 0 | close(fout); |
1958 | 0 | return 0; |
1959 | 0 | } |
1960 | | |
1961 | | /* Assign the replacement descriptor. */ |
1962 | 0 | *p = fout; |
1963 | 0 | return 1; |
1964 | 0 | } |
1965 | | |
1966 | | static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]) |
1967 | 0 | { |
1968 | | /* Close the existing descriptor. */ |
1969 | 0 | kwsysProcessCleanupDescriptor(p); |
1970 | | |
1971 | | /* Set close-on-exec flag on the pipe's ends. The proper end will |
1972 | | be dup2-ed into the standard descriptor number after fork but |
1973 | | before exec. */ |
1974 | 0 | if ((fcntl(des[0], F_SETFD, FD_CLOEXEC) < 0) || |
1975 | 0 | (fcntl(des[1], F_SETFD, FD_CLOEXEC) < 0)) { |
1976 | 0 | return 0; |
1977 | 0 | } |
1978 | | |
1979 | | /* Assign the replacement descriptor. */ |
1980 | 0 | *p = des[1]; |
1981 | 0 | return 1; |
1982 | 0 | } |
1983 | | |
1984 | | /* Get the time at which either the process or user timeout will |
1985 | | expire. Returns 1 if the user timeout is first, and 0 otherwise. */ |
1986 | | static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, |
1987 | | double const* userTimeout, |
1988 | | kwsysProcessTime* timeoutTime) |
1989 | 0 | { |
1990 | | /* The first time this is called, we need to calculate the time at |
1991 | | which the child will timeout. */ |
1992 | 0 | if (cp->Timeout > 0 && cp->TimeoutTime.tv_sec < 0) { |
1993 | 0 | kwsysProcessTime length = kwsysProcessTimeFromDouble(cp->Timeout); |
1994 | 0 | cp->TimeoutTime = kwsysProcessTimeAdd(cp->StartTime, length); |
1995 | 0 | } |
1996 | | |
1997 | | /* Start with process timeout. */ |
1998 | 0 | *timeoutTime = cp->TimeoutTime; |
1999 | | |
2000 | | /* Check if the user timeout is earlier. */ |
2001 | 0 | if (userTimeout) { |
2002 | 0 | kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent(); |
2003 | 0 | kwsysProcessTime userTimeoutLength = |
2004 | 0 | kwsysProcessTimeFromDouble(*userTimeout); |
2005 | 0 | kwsysProcessTime userTimeoutTime = |
2006 | 0 | kwsysProcessTimeAdd(currentTime, userTimeoutLength); |
2007 | 0 | if (timeoutTime->tv_sec < 0 || |
2008 | 0 | kwsysProcessTimeLess(userTimeoutTime, *timeoutTime)) { |
2009 | 0 | *timeoutTime = userTimeoutTime; |
2010 | 0 | return 1; |
2011 | 0 | } |
2012 | 0 | } |
2013 | 0 | return 0; |
2014 | 0 | } |
2015 | | |
2016 | | #if defined(__clang__) && defined(__has_warning) |
2017 | | # if __has_warning("-Wshorten-64-to-32") |
2018 | | # pragma clang diagnostic push |
2019 | | # pragma clang diagnostic ignored "-Wshorten-64-to-32" |
2020 | | # define KWSYSPE_CLANG_DIAG_WSHORTEN |
2021 | | # endif |
2022 | | #endif |
2023 | | |
2024 | | /* Get the length of time before the given timeout time arrives. |
2025 | | Returns 1 if the time has already arrived, and 0 otherwise. */ |
2026 | | static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime, |
2027 | | double const* userTimeout, |
2028 | | kwsysProcessTimeNative* timeoutLength, |
2029 | | int zeroIsExpired) |
2030 | 0 | { |
2031 | 0 | if (timeoutTime->tv_sec < 0) { |
2032 | | /* No timeout time has been requested. */ |
2033 | 0 | return 0; |
2034 | 0 | } |
2035 | | /* Calculate the remaining time. */ |
2036 | 0 | kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent(); |
2037 | 0 | kwsysProcessTime timeLeft = |
2038 | 0 | kwsysProcessTimeSubtract(*timeoutTime, currentTime); |
2039 | 0 | if (timeLeft.tv_sec < 0 && userTimeout && *userTimeout <= 0) { |
2040 | | /* Caller has explicitly requested a zero timeout. */ |
2041 | 0 | timeLeft.tv_sec = 0; |
2042 | 0 | timeLeft.tv_usec = 0; |
2043 | 0 | } |
2044 | |
|
2045 | 0 | if (timeLeft.tv_sec < 0 || |
2046 | 0 | (timeLeft.tv_sec == 0 && timeLeft.tv_usec == 0 && zeroIsExpired)) { |
2047 | | /* Timeout has already expired. */ |
2048 | 0 | return 1; |
2049 | 0 | } |
2050 | | /* There is some time left. */ |
2051 | 0 | timeoutLength->tv_sec = timeLeft.tv_sec; |
2052 | 0 | timeoutLength->tv_usec = timeLeft.tv_usec; |
2053 | 0 | return 0; |
2054 | 0 | } |
2055 | | |
2056 | | static kwsysProcessTime kwsysProcessTimeGetCurrent(void) |
2057 | 0 | { |
2058 | 0 | kwsysProcessTime current; |
2059 | 0 | kwsysProcessTimeNative current_native; |
2060 | 0 | #if KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC |
2061 | 0 | struct timespec current_timespec; |
2062 | 0 | clock_gettime(CLOCK_MONOTONIC, ¤t_timespec); |
2063 | |
|
2064 | 0 | current_native.tv_sec = current_timespec.tv_sec; |
2065 | 0 | current_native.tv_usec = current_timespec.tv_nsec / 1000; |
2066 | | #else |
2067 | | gettimeofday(¤t_native, 0); |
2068 | | #endif |
2069 | 0 | current.tv_sec = (long)current_native.tv_sec; |
2070 | 0 | current.tv_usec = (long)current_native.tv_usec; |
2071 | 0 | return current; |
2072 | 0 | } |
2073 | | |
2074 | | #if defined(KWSYSPE_CLANG_DIAG_WSHORTEN) |
2075 | | # undef KWSYSPE_CLANG_DIAG_WSHORTEN |
2076 | | # pragma clang diagnostic pop |
2077 | | #endif |
2078 | | |
2079 | | static double kwsysProcessTimeToDouble(kwsysProcessTime t) |
2080 | 0 | { |
2081 | 0 | return (double)t.tv_sec + (double)(t.tv_usec) * 0.000001; |
2082 | 0 | } |
2083 | | |
2084 | | static kwsysProcessTime kwsysProcessTimeFromDouble(double d) |
2085 | 0 | { |
2086 | 0 | kwsysProcessTime t; |
2087 | 0 | t.tv_sec = (long)d; |
2088 | 0 | t.tv_usec = (long)((d - (double)(t.tv_sec)) * 1000000); |
2089 | 0 | return t; |
2090 | 0 | } |
2091 | | |
2092 | | static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2) |
2093 | 0 | { |
2094 | 0 | return ((in1.tv_sec < in2.tv_sec) || |
2095 | 0 | ((in1.tv_sec == in2.tv_sec) && (in1.tv_usec < in2.tv_usec))); |
2096 | 0 | } |
2097 | | |
2098 | | static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, |
2099 | | kwsysProcessTime in2) |
2100 | 0 | { |
2101 | 0 | kwsysProcessTime out; |
2102 | 0 | out.tv_sec = in1.tv_sec + in2.tv_sec; |
2103 | 0 | out.tv_usec = in1.tv_usec + in2.tv_usec; |
2104 | 0 | if (out.tv_usec >= 1000000) { |
2105 | 0 | out.tv_usec -= 1000000; |
2106 | 0 | out.tv_sec += 1; |
2107 | 0 | } |
2108 | 0 | return out; |
2109 | 0 | } |
2110 | | |
2111 | | static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, |
2112 | | kwsysProcessTime in2) |
2113 | 0 | { |
2114 | 0 | kwsysProcessTime out; |
2115 | 0 | out.tv_sec = in1.tv_sec - in2.tv_sec; |
2116 | 0 | out.tv_usec = in1.tv_usec - in2.tv_usec; |
2117 | 0 | if (out.tv_usec < 0) { |
2118 | 0 | out.tv_usec += 1000000; |
2119 | 0 | out.tv_sec -= 1; |
2120 | 0 | } |
2121 | 0 | return out; |
2122 | 0 | } |
2123 | | |
2124 | | #define KWSYSPE_CASE(type, str) \ |
2125 | 0 | cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_##type; \ |
2126 | 0 | strcpy(cp->ProcessResults[idx].ExitExceptionString, str) |
2127 | | static void kwsysProcessSetExitExceptionByIndex(kwsysProcess* cp, int sig, |
2128 | | int idx) |
2129 | 0 | { |
2130 | 0 | switch (sig) { |
2131 | 0 | #ifdef SIGSEGV |
2132 | 0 | case SIGSEGV: |
2133 | 0 | KWSYSPE_CASE(Fault, "Segmentation fault"); |
2134 | 0 | break; |
2135 | 0 | #endif |
2136 | 0 | #ifdef SIGBUS |
2137 | 0 | # if !defined(SIGSEGV) || SIGBUS != SIGSEGV |
2138 | 0 | case SIGBUS: |
2139 | 0 | KWSYSPE_CASE(Fault, "Bus error"); |
2140 | 0 | break; |
2141 | 0 | # endif |
2142 | 0 | #endif |
2143 | 0 | #ifdef SIGFPE |
2144 | 0 | case SIGFPE: |
2145 | 0 | KWSYSPE_CASE(Numerical, "Floating-point exception"); |
2146 | 0 | break; |
2147 | 0 | #endif |
2148 | 0 | #ifdef SIGILL |
2149 | 0 | case SIGILL: |
2150 | 0 | KWSYSPE_CASE(Illegal, "Illegal instruction"); |
2151 | 0 | break; |
2152 | 0 | #endif |
2153 | 0 | #ifdef SIGINT |
2154 | 0 | case SIGINT: |
2155 | 0 | KWSYSPE_CASE(Interrupt, "User interrupt"); |
2156 | 0 | break; |
2157 | 0 | #endif |
2158 | 0 | #ifdef SIGABRT |
2159 | 0 | case SIGABRT: |
2160 | 0 | KWSYSPE_CASE(Other, "Subprocess aborted"); |
2161 | 0 | break; |
2162 | 0 | #endif |
2163 | 0 | #ifdef SIGKILL |
2164 | 0 | case SIGKILL: |
2165 | 0 | KWSYSPE_CASE(Other, "Subprocess killed"); |
2166 | 0 | break; |
2167 | 0 | #endif |
2168 | 0 | #ifdef SIGTERM |
2169 | 0 | case SIGTERM: |
2170 | 0 | KWSYSPE_CASE(Other, "Subprocess terminated"); |
2171 | 0 | break; |
2172 | 0 | #endif |
2173 | 0 | #ifdef SIGHUP |
2174 | 0 | case SIGHUP: |
2175 | 0 | KWSYSPE_CASE(Other, "SIGHUP"); |
2176 | 0 | break; |
2177 | 0 | #endif |
2178 | 0 | #ifdef SIGQUIT |
2179 | 0 | case SIGQUIT: |
2180 | 0 | KWSYSPE_CASE(Other, "SIGQUIT"); |
2181 | 0 | break; |
2182 | 0 | #endif |
2183 | 0 | #ifdef SIGTRAP |
2184 | 0 | case SIGTRAP: |
2185 | 0 | KWSYSPE_CASE(Other, "SIGTRAP"); |
2186 | 0 | break; |
2187 | 0 | #endif |
2188 | 0 | #ifdef SIGIOT |
2189 | | # if !defined(SIGABRT) || SIGIOT != SIGABRT |
2190 | | case SIGIOT: |
2191 | | KWSYSPE_CASE(Other, "SIGIOT"); |
2192 | | break; |
2193 | | # endif |
2194 | 0 | #endif |
2195 | 0 | #ifdef SIGUSR1 |
2196 | 0 | case SIGUSR1: |
2197 | 0 | KWSYSPE_CASE(Other, "SIGUSR1"); |
2198 | 0 | break; |
2199 | 0 | #endif |
2200 | 0 | #ifdef SIGUSR2 |
2201 | 0 | case SIGUSR2: |
2202 | 0 | KWSYSPE_CASE(Other, "SIGUSR2"); |
2203 | 0 | break; |
2204 | 0 | #endif |
2205 | 0 | #ifdef SIGPIPE |
2206 | 0 | case SIGPIPE: |
2207 | 0 | KWSYSPE_CASE(Other, "SIGPIPE"); |
2208 | 0 | break; |
2209 | 0 | #endif |
2210 | 0 | #ifdef SIGALRM |
2211 | 0 | case SIGALRM: |
2212 | 0 | KWSYSPE_CASE(Other, "SIGALRM"); |
2213 | 0 | break; |
2214 | 0 | #endif |
2215 | 0 | #ifdef SIGSTKFLT |
2216 | 0 | case SIGSTKFLT: |
2217 | 0 | KWSYSPE_CASE(Other, "SIGSTKFLT"); |
2218 | 0 | break; |
2219 | 0 | #endif |
2220 | 0 | #ifdef SIGCHLD |
2221 | 0 | case SIGCHLD: |
2222 | 0 | KWSYSPE_CASE(Other, "SIGCHLD"); |
2223 | 0 | break; |
2224 | | #elif defined(SIGCLD) |
2225 | | case SIGCLD: |
2226 | | KWSYSPE_CASE(Other, "SIGCLD"); |
2227 | | break; |
2228 | | #endif |
2229 | 0 | #ifdef SIGCONT |
2230 | 0 | case SIGCONT: |
2231 | 0 | KWSYSPE_CASE(Other, "SIGCONT"); |
2232 | 0 | break; |
2233 | 0 | #endif |
2234 | 0 | #ifdef SIGSTOP |
2235 | 0 | case SIGSTOP: |
2236 | 0 | KWSYSPE_CASE(Other, "SIGSTOP"); |
2237 | 0 | break; |
2238 | 0 | #endif |
2239 | 0 | #ifdef SIGTSTP |
2240 | 0 | case SIGTSTP: |
2241 | 0 | KWSYSPE_CASE(Other, "SIGTSTP"); |
2242 | 0 | break; |
2243 | 0 | #endif |
2244 | 0 | #ifdef SIGTTIN |
2245 | 0 | case SIGTTIN: |
2246 | 0 | KWSYSPE_CASE(Other, "SIGTTIN"); |
2247 | 0 | break; |
2248 | 0 | #endif |
2249 | 0 | #ifdef SIGTTOU |
2250 | 0 | case SIGTTOU: |
2251 | 0 | KWSYSPE_CASE(Other, "SIGTTOU"); |
2252 | 0 | break; |
2253 | 0 | #endif |
2254 | 0 | #ifdef SIGURG |
2255 | 0 | case SIGURG: |
2256 | 0 | KWSYSPE_CASE(Other, "SIGURG"); |
2257 | 0 | break; |
2258 | 0 | #endif |
2259 | 0 | #ifdef SIGXCPU |
2260 | 0 | case SIGXCPU: |
2261 | 0 | KWSYSPE_CASE(Other, "SIGXCPU"); |
2262 | 0 | break; |
2263 | 0 | #endif |
2264 | 0 | #ifdef SIGXFSZ |
2265 | 0 | case SIGXFSZ: |
2266 | 0 | KWSYSPE_CASE(Other, "SIGXFSZ"); |
2267 | 0 | break; |
2268 | 0 | #endif |
2269 | 0 | #ifdef SIGVTALRM |
2270 | 0 | case SIGVTALRM: |
2271 | 0 | KWSYSPE_CASE(Other, "SIGVTALRM"); |
2272 | 0 | break; |
2273 | 0 | #endif |
2274 | 0 | #ifdef SIGPROF |
2275 | 0 | case SIGPROF: |
2276 | 0 | KWSYSPE_CASE(Other, "SIGPROF"); |
2277 | 0 | break; |
2278 | 0 | #endif |
2279 | 0 | #ifdef SIGWINCH |
2280 | 0 | case SIGWINCH: |
2281 | 0 | KWSYSPE_CASE(Other, "SIGWINCH"); |
2282 | 0 | break; |
2283 | 0 | #endif |
2284 | 0 | #ifdef SIGPOLL |
2285 | 0 | case SIGPOLL: |
2286 | 0 | KWSYSPE_CASE(Other, "SIGPOLL"); |
2287 | 0 | break; |
2288 | 0 | #endif |
2289 | 0 | #ifdef SIGIO |
2290 | | # if !defined(SIGPOLL) || SIGIO != SIGPOLL |
2291 | | case SIGIO: |
2292 | | KWSYSPE_CASE(Other, "SIGIO"); |
2293 | | break; |
2294 | | # endif |
2295 | 0 | #endif |
2296 | 0 | #ifdef SIGPWR |
2297 | 0 | case SIGPWR: |
2298 | 0 | KWSYSPE_CASE(Other, "SIGPWR"); |
2299 | 0 | break; |
2300 | 0 | #endif |
2301 | 0 | #ifdef SIGSYS |
2302 | 0 | case SIGSYS: |
2303 | 0 | KWSYSPE_CASE(Other, "SIGSYS"); |
2304 | 0 | break; |
2305 | 0 | #endif |
2306 | | #ifdef SIGUNUSED |
2307 | | # if !defined(SIGSYS) || SIGUNUSED != SIGSYS |
2308 | | case SIGUNUSED: |
2309 | | KWSYSPE_CASE(Other, "SIGUNUSED"); |
2310 | | break; |
2311 | | # endif |
2312 | | #endif |
2313 | 0 | default: |
2314 | 0 | cp->ProcessResults[idx].ExitException = kwsysProcess_Exception_Other; |
2315 | 0 | snprintf(cp->ProcessResults[idx].ExitExceptionString, |
2316 | 0 | KWSYSPE_PIPE_BUFFER_SIZE + 1, "Signal %d", sig); |
2317 | 0 | break; |
2318 | 0 | } |
2319 | 0 | } |
2320 | | #undef KWSYSPE_CASE |
2321 | | |
2322 | | /* When the child process encounters an error before its program is |
2323 | | invoked, this is called to report the error to the parent and |
2324 | | exit. */ |
2325 | | static void kwsysProcessChildErrorExit(int errorPipe) |
2326 | 0 | { |
2327 | | /* Construct the error message. */ |
2328 | 0 | char buffer[KWSYSPE_PIPE_BUFFER_SIZE]; |
2329 | 0 | kwsysProcess_ssize_t result; |
2330 | 0 | strncpy(buffer, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE); |
2331 | 0 | buffer[KWSYSPE_PIPE_BUFFER_SIZE - 1] = '\0'; |
2332 | | |
2333 | | /* Report the error to the parent through the special pipe. */ |
2334 | 0 | result = write(errorPipe, buffer, strlen(buffer)); |
2335 | 0 | (void)result; |
2336 | | |
2337 | | /* Terminate without cleanup. */ |
2338 | 0 | _exit(1); |
2339 | 0 | } |
2340 | | |
2341 | | /* Restores all signal handlers to their default values. */ |
2342 | | static void kwsysProcessRestoreDefaultSignalHandlers(void) |
2343 | 0 | { |
2344 | 0 | struct sigaction act; |
2345 | 0 | memset(&act, 0, sizeof(struct sigaction)); |
2346 | 0 | act.sa_handler = SIG_DFL; |
2347 | 0 | #ifdef SIGHUP |
2348 | 0 | sigaction(SIGHUP, &act, 0); |
2349 | 0 | #endif |
2350 | 0 | #ifdef SIGINT |
2351 | 0 | sigaction(SIGINT, &act, 0); |
2352 | 0 | #endif |
2353 | 0 | #ifdef SIGQUIT |
2354 | 0 | sigaction(SIGQUIT, &act, 0); |
2355 | 0 | #endif |
2356 | 0 | #ifdef SIGILL |
2357 | 0 | sigaction(SIGILL, &act, 0); |
2358 | 0 | #endif |
2359 | 0 | #ifdef SIGTRAP |
2360 | 0 | sigaction(SIGTRAP, &act, 0); |
2361 | 0 | #endif |
2362 | 0 | #ifdef SIGABRT |
2363 | 0 | sigaction(SIGABRT, &act, 0); |
2364 | 0 | #endif |
2365 | 0 | #ifdef SIGIOT |
2366 | 0 | sigaction(SIGIOT, &act, 0); |
2367 | 0 | #endif |
2368 | 0 | #ifdef SIGBUS |
2369 | 0 | sigaction(SIGBUS, &act, 0); |
2370 | 0 | #endif |
2371 | 0 | #ifdef SIGFPE |
2372 | 0 | sigaction(SIGFPE, &act, 0); |
2373 | 0 | #endif |
2374 | 0 | #ifdef SIGUSR1 |
2375 | 0 | sigaction(SIGUSR1, &act, 0); |
2376 | 0 | #endif |
2377 | 0 | #ifdef SIGSEGV |
2378 | 0 | sigaction(SIGSEGV, &act, 0); |
2379 | 0 | #endif |
2380 | 0 | #ifdef SIGUSR2 |
2381 | 0 | sigaction(SIGUSR2, &act, 0); |
2382 | 0 | #endif |
2383 | 0 | #ifdef SIGPIPE |
2384 | 0 | sigaction(SIGPIPE, &act, 0); |
2385 | 0 | #endif |
2386 | 0 | #ifdef SIGALRM |
2387 | 0 | sigaction(SIGALRM, &act, 0); |
2388 | 0 | #endif |
2389 | 0 | #ifdef SIGTERM |
2390 | 0 | sigaction(SIGTERM, &act, 0); |
2391 | 0 | #endif |
2392 | 0 | #ifdef SIGSTKFLT |
2393 | 0 | sigaction(SIGSTKFLT, &act, 0); |
2394 | 0 | #endif |
2395 | 0 | #ifdef SIGCLD |
2396 | 0 | sigaction(SIGCLD, &act, 0); |
2397 | 0 | #endif |
2398 | 0 | #ifdef SIGCHLD |
2399 | 0 | sigaction(SIGCHLD, &act, 0); |
2400 | 0 | #endif |
2401 | 0 | #ifdef SIGCONT |
2402 | 0 | sigaction(SIGCONT, &act, 0); |
2403 | 0 | #endif |
2404 | 0 | #ifdef SIGTSTP |
2405 | 0 | sigaction(SIGTSTP, &act, 0); |
2406 | 0 | #endif |
2407 | 0 | #ifdef SIGTTIN |
2408 | 0 | sigaction(SIGTTIN, &act, 0); |
2409 | 0 | #endif |
2410 | 0 | #ifdef SIGTTOU |
2411 | 0 | sigaction(SIGTTOU, &act, 0); |
2412 | 0 | #endif |
2413 | 0 | #ifdef SIGURG |
2414 | 0 | sigaction(SIGURG, &act, 0); |
2415 | 0 | #endif |
2416 | 0 | #ifdef SIGXCPU |
2417 | 0 | sigaction(SIGXCPU, &act, 0); |
2418 | 0 | #endif |
2419 | 0 | #ifdef SIGXFSZ |
2420 | 0 | sigaction(SIGXFSZ, &act, 0); |
2421 | 0 | #endif |
2422 | 0 | #ifdef SIGVTALRM |
2423 | 0 | sigaction(SIGVTALRM, &act, 0); |
2424 | 0 | #endif |
2425 | 0 | #ifdef SIGPROF |
2426 | 0 | sigaction(SIGPROF, &act, 0); |
2427 | 0 | #endif |
2428 | 0 | #ifdef SIGWINCH |
2429 | 0 | sigaction(SIGWINCH, &act, 0); |
2430 | 0 | #endif |
2431 | 0 | #ifdef SIGPOLL |
2432 | 0 | sigaction(SIGPOLL, &act, 0); |
2433 | 0 | #endif |
2434 | 0 | #ifdef SIGIO |
2435 | 0 | sigaction(SIGIO, &act, 0); |
2436 | 0 | #endif |
2437 | 0 | #ifdef SIGPWR |
2438 | 0 | sigaction(SIGPWR, &act, 0); |
2439 | 0 | #endif |
2440 | 0 | #ifdef SIGSYS |
2441 | 0 | sigaction(SIGSYS, &act, 0); |
2442 | 0 | #endif |
2443 | | #ifdef SIGUNUSED |
2444 | | sigaction(SIGUNUSED, &act, 0); |
2445 | | #endif |
2446 | 0 | } |
2447 | | |
2448 | | static void kwsysProcessExit(void) |
2449 | 0 | { |
2450 | 0 | _exit(0); |
2451 | 0 | } |
2452 | | |
2453 | | #if !defined(__VMS) |
2454 | | static pid_t kwsysProcessFork(kwsysProcess* cp, |
2455 | | kwsysProcessCreateInformation* si) |
2456 | 0 | { |
2457 | | /* Create a detached process if requested. */ |
2458 | 0 | if (cp->OptionDetach) { |
2459 | | /* Create an intermediate process. */ |
2460 | 0 | pid_t middle_pid = fork(); |
2461 | 0 | if (middle_pid < 0) { |
2462 | | /* Fork failed. Return as if we were not detaching. */ |
2463 | 0 | return middle_pid; |
2464 | 0 | } |
2465 | 0 | if (middle_pid == 0) { |
2466 | | /* This is the intermediate process. Create the real child. */ |
2467 | 0 | pid_t child_pid = fork(); |
2468 | 0 | if (child_pid == 0) { |
2469 | | /* This is the real child process. There is nothing to do here. */ |
2470 | 0 | return 0; |
2471 | 0 | } |
2472 | | /* Use the error pipe to report the pid to the real parent. */ |
2473 | 0 | while ((write(si->ErrorPipe[1], &child_pid, sizeof(child_pid)) < 0) && |
2474 | 0 | (errno == EINTR)) { |
2475 | 0 | } |
2476 | | |
2477 | | /* Exit without cleanup. The parent holds all resources. */ |
2478 | 0 | kwsysProcessExit(); |
2479 | 0 | return 0; /* Never reached, but avoids SunCC warning. */ |
2480 | 0 | } |
2481 | | /* This is the original parent process. The intermediate |
2482 | | process will use the error pipe to report the pid of the |
2483 | | detached child. */ |
2484 | 0 | pid_t child_pid; |
2485 | 0 | int status; |
2486 | 0 | while ((read(si->ErrorPipe[0], &child_pid, sizeof(child_pid)) < 0) && |
2487 | 0 | (errno == EINTR)) { |
2488 | 0 | } |
2489 | | |
2490 | | /* Wait for the intermediate process to exit and clean it up. */ |
2491 | 0 | while ((waitpid(middle_pid, &status, 0) < 0) && (errno == EINTR)) { |
2492 | 0 | } |
2493 | 0 | return child_pid; |
2494 | 0 | } |
2495 | | /* Not creating a detached process. Use normal fork. */ |
2496 | 0 | return fork(); |
2497 | 0 | } |
2498 | | #endif |
2499 | | |
2500 | | /* We try to obtain process information by invoking the ps command. |
2501 | | Here we define the command to call on each platform and the |
2502 | | corresponding parsing format string. The parsing format should |
2503 | | have two integers to store: the pid and then the ppid. */ |
2504 | | #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ |
2505 | | defined(__NetBSD__) || defined(__OpenBSD__) || defined(__GLIBC__) || \ |
2506 | | defined(__GNU__) |
2507 | 0 | # define KWSYSPE_PS_COMMAND "ps axo pid,ppid" |
2508 | 0 | # define KWSYSPE_PS_FORMAT "%d %d\n" |
2509 | | #elif defined(__sun) && (defined(__SVR4) || defined(__svr4__)) /* Solaris */ |
2510 | | # define KWSYSPE_PS_COMMAND "ps -e -o pid,ppid" |
2511 | | # define KWSYSPE_PS_FORMAT "%d %d\n" |
2512 | | #elif defined(__hpux) || defined(__sun__) || defined(__sgi) || \ |
2513 | | defined(_AIX) || defined(__sparc) |
2514 | | # define KWSYSPE_PS_COMMAND "ps -ef" |
2515 | | # define KWSYSPE_PS_FORMAT "%*s %d %d %*[^\n]\n" |
2516 | | #elif defined(__QNX__) |
2517 | | # define KWSYSPE_PS_COMMAND "ps -Af" |
2518 | | # define KWSYSPE_PS_FORMAT "%*d %d %d %*[^\n]\n" |
2519 | | #elif defined(__CYGWIN__) |
2520 | | # define KWSYSPE_PS_COMMAND "ps aux" |
2521 | | # define KWSYSPE_PS_FORMAT "%d %d %*[^\n]\n" |
2522 | | #endif |
2523 | | |
2524 | | void kwsysProcess_KillPID(unsigned long process_id) |
2525 | 0 | { |
2526 | 0 | kwsysProcessKill((pid_t)process_id); |
2527 | 0 | } |
2528 | | |
2529 | | static void kwsysProcessKill(pid_t process_id) |
2530 | 0 | { |
2531 | 0 | #if defined(__linux__) || defined(__CYGWIN__) |
2532 | 0 | DIR* procdir; |
2533 | 0 | #endif |
2534 | | |
2535 | | /* Suspend the process to be sure it will not create more children. */ |
2536 | 0 | kill(process_id, SIGSTOP); |
2537 | |
|
2538 | | #if defined(__CYGWIN__) |
2539 | | /* Some Cygwin versions seem to need help here. Give up our time slice |
2540 | | so that the child can process SIGSTOP before we send SIGKILL. */ |
2541 | | usleep(1); |
2542 | | #endif |
2543 | | |
2544 | | /* Kill all children if we can find them. */ |
2545 | 0 | #if defined(__linux__) || defined(__CYGWIN__) |
2546 | | /* First try using the /proc filesystem. */ |
2547 | 0 | if ((procdir = opendir("/proc"))) { |
2548 | | # if defined(MAXPATHLEN) |
2549 | | char fname[MAXPATHLEN]; |
2550 | | # elif defined(PATH_MAX) |
2551 | | char fname[PATH_MAX]; |
2552 | | # else |
2553 | 0 | char fname[4096]; |
2554 | 0 | # endif |
2555 | 0 | char buffer[KWSYSPE_PIPE_BUFFER_SIZE + 1]; |
2556 | 0 | struct dirent* d; |
2557 | | |
2558 | | /* Each process has a directory in /proc whose name is the pid. |
2559 | | Within this directory is a file called stat that has the |
2560 | | following format: |
2561 | | |
2562 | | pid (command line) status ppid ... |
2563 | | |
2564 | | We want to get the ppid for all processes. Those that have |
2565 | | process_id as their parent should be recursively killed. */ |
2566 | 0 | for (d = readdir(procdir); d; d = readdir(procdir)) { |
2567 | 0 | int pid; |
2568 | 0 | if (sscanf(d->d_name, "%d", &pid) == 1 && pid != 0) { |
2569 | 0 | struct stat finfo; |
2570 | 0 | snprintf(fname, sizeof(fname), "/proc/%d/stat", pid); |
2571 | 0 | if (stat(fname, &finfo) == 0) { |
2572 | 0 | FILE* f = fopen(fname, "r"); |
2573 | 0 | if (f) { |
2574 | 0 | size_t nread = fread(buffer, 1, KWSYSPE_PIPE_BUFFER_SIZE, f); |
2575 | 0 | fclose(f); |
2576 | 0 | buffer[nread] = '\0'; |
2577 | 0 | if (nread > 0) { |
2578 | 0 | char const* rparen = strrchr(buffer, ')'); |
2579 | 0 | int ppid; |
2580 | 0 | if (rparen && (sscanf(rparen + 1, "%*s %d", &ppid) == 1)) { |
2581 | 0 | if (ppid == process_id) { |
2582 | | /* Recursively kill this child and its children. */ |
2583 | 0 | kwsysProcessKill(pid); |
2584 | 0 | } |
2585 | 0 | } |
2586 | 0 | } |
2587 | 0 | } |
2588 | 0 | } |
2589 | 0 | } |
2590 | 0 | } |
2591 | 0 | closedir(procdir); |
2592 | 0 | } else |
2593 | 0 | #endif |
2594 | 0 | { |
2595 | 0 | #if defined(KWSYSPE_PS_COMMAND) |
2596 | | /* Try running "ps" to get the process information. */ |
2597 | 0 | FILE* ps = popen(KWSYSPE_PS_COMMAND, "r"); |
2598 | | |
2599 | | /* Make sure the process started and provided a valid header. */ |
2600 | 0 | if (ps && fscanf(ps, "%*[^\n]\n") != EOF) { |
2601 | | /* Look for processes whose parent is the process being killed. */ |
2602 | 0 | int pid; |
2603 | 0 | int ppid; |
2604 | 0 | while (fscanf(ps, KWSYSPE_PS_FORMAT, &pid, &ppid) == 2) { |
2605 | 0 | if (ppid == process_id) { |
2606 | | /* Recursively kill this child and its children. */ |
2607 | 0 | kwsysProcessKill(pid); |
2608 | 0 | } |
2609 | 0 | } |
2610 | 0 | } |
2611 | | |
2612 | | /* We are done with the ps process. */ |
2613 | 0 | if (ps) { |
2614 | 0 | pclose(ps); |
2615 | 0 | } |
2616 | 0 | #endif |
2617 | 0 | } |
2618 | | |
2619 | | /* Kill the process. */ |
2620 | 0 | kill(process_id, SIGKILL); |
2621 | |
|
2622 | | #if defined(__APPLE__) |
2623 | | /* On OS X 10.3 the above SIGSTOP occasionally prevents the SIGKILL |
2624 | | from working. Just in case, we resume the child and kill it |
2625 | | again. There is a small race condition in this obscure case. If |
2626 | | the child manages to fork again between these two signals, we |
2627 | | will not catch its children. */ |
2628 | | kill(process_id, SIGCONT); |
2629 | | kill(process_id, SIGKILL); |
2630 | | #endif |
2631 | 0 | } |
2632 | | |
2633 | | #if defined(__VMS) |
2634 | | int decc$feature_get_index(char const* name); |
2635 | | int decc$feature_set_value(int index, int mode, int value); |
2636 | | static int kwsysProcessSetVMSFeature(char const* name, int value) |
2637 | | { |
2638 | | int i; |
2639 | | errno = 0; |
2640 | | i = decc$feature_get_index(name); |
2641 | | return i >= 0 && (decc$feature_set_value(i, 1, value) >= 0 || errno == 0); |
2642 | | } |
2643 | | #endif |
2644 | | |
2645 | | /* Global set of executing processes for use by the signal handler. |
2646 | | This global instance will be zero-initialized by the compiler. */ |
2647 | | typedef struct kwsysProcessInstances_s |
2648 | | { |
2649 | | int Count; |
2650 | | int Size; |
2651 | | kwsysProcess** Processes; |
2652 | | } kwsysProcessInstances; |
2653 | | static kwsysProcessInstances kwsysProcesses; |
2654 | | |
2655 | | /* The old SIGCHLD / SIGINT / SIGTERM handlers. */ |
2656 | | static struct sigaction kwsysProcessesOldSigChldAction; |
2657 | | static struct sigaction kwsysProcessesOldSigIntAction; |
2658 | | static struct sigaction kwsysProcessesOldSigTermAction; |
2659 | | |
2660 | | static void kwsysProcessesUpdate(kwsysProcessInstances* newProcesses) |
2661 | 0 | { |
2662 | | /* Block signals while we update the set of pipes to check. |
2663 | | TODO: sigprocmask is undefined for threaded apps. See |
2664 | | pthread_sigmask. */ |
2665 | 0 | sigset_t newset; |
2666 | 0 | sigset_t oldset; |
2667 | 0 | sigemptyset(&newset); |
2668 | 0 | sigaddset(&newset, SIGCHLD); |
2669 | 0 | sigaddset(&newset, SIGINT); |
2670 | 0 | sigaddset(&newset, SIGTERM); |
2671 | 0 | sigprocmask(SIG_BLOCK, &newset, &oldset); |
2672 | | |
2673 | | /* Store the new set in that seen by the signal handler. */ |
2674 | 0 | kwsysProcesses = *newProcesses; |
2675 | | |
2676 | | /* Restore the signal mask to the previous setting. */ |
2677 | 0 | sigprocmask(SIG_SETMASK, &oldset, 0); |
2678 | 0 | } |
2679 | | |
2680 | | static int kwsysProcessesAdd(kwsysProcess* cp) |
2681 | 0 | { |
2682 | | /* Create a pipe through which the signal handler can notify the |
2683 | | given process object that a child has exited. */ |
2684 | 0 | { |
2685 | | /* Create the pipe. */ |
2686 | 0 | int p[2]; |
2687 | 0 | if (pipe(p KWSYSPE_VMS_NONBLOCK) < 0) { |
2688 | 0 | return 0; |
2689 | 0 | } |
2690 | | |
2691 | | /* Store the pipes now to be sure they are cleaned up later. */ |
2692 | 0 | cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL] = p[0]; |
2693 | 0 | cp->SignalPipe = p[1]; |
2694 | | |
2695 | | /* Switch the pipe to non-blocking mode so that reading a byte can |
2696 | | be an atomic test-and-set. */ |
2697 | 0 | if (!kwsysProcessSetNonBlocking(p[0]) || |
2698 | 0 | !kwsysProcessSetNonBlocking(p[1])) { |
2699 | 0 | return 0; |
2700 | 0 | } |
2701 | | |
2702 | | /* The children do not need this pipe. Set close-on-exec flag on |
2703 | | the pipe's ends. */ |
2704 | 0 | if ((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || |
2705 | 0 | (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) { |
2706 | 0 | return 0; |
2707 | 0 | } |
2708 | 0 | } |
2709 | | |
2710 | | /* Attempt to add the given signal pipe to the signal handler set. */ |
2711 | 0 | { |
2712 | | |
2713 | | /* Make sure there is enough space for the new signal pipe. */ |
2714 | 0 | kwsysProcessInstances oldProcesses = kwsysProcesses; |
2715 | 0 | kwsysProcessInstances newProcesses = oldProcesses; |
2716 | 0 | if (oldProcesses.Count == oldProcesses.Size) { |
2717 | | /* Start with enough space for a small number of process instances |
2718 | | and double the size each time more is needed. */ |
2719 | 0 | newProcesses.Size = oldProcesses.Size ? oldProcesses.Size * 2 : 4; |
2720 | | |
2721 | | /* Try allocating the new block of memory. */ |
2722 | 0 | if ((newProcesses.Processes = ((kwsysProcess**)malloc( |
2723 | 0 | (size_t)(newProcesses.Size) * sizeof(kwsysProcess*))))) { |
2724 | | /* Copy the old pipe set to the new memory. */ |
2725 | 0 | if (oldProcesses.Count > 0) { |
2726 | 0 | memcpy(newProcesses.Processes, oldProcesses.Processes, |
2727 | 0 | ((size_t)(oldProcesses.Count) * sizeof(kwsysProcess*))); |
2728 | 0 | } |
2729 | 0 | } else { |
2730 | | /* Failed to allocate memory for the new signal pipe set. */ |
2731 | 0 | return 0; |
2732 | 0 | } |
2733 | 0 | } |
2734 | | |
2735 | | /* Append the new signal pipe to the set. */ |
2736 | 0 | newProcesses.Processes[newProcesses.Count++] = cp; |
2737 | | |
2738 | | /* Store the new set in that seen by the signal handler. */ |
2739 | 0 | kwsysProcessesUpdate(&newProcesses); |
2740 | | |
2741 | | /* Free the original pipes if new ones were allocated. */ |
2742 | 0 | if (newProcesses.Processes != oldProcesses.Processes) { |
2743 | 0 | free(oldProcesses.Processes); |
2744 | 0 | } |
2745 | | |
2746 | | /* If this is the first process, enable the signal handler. */ |
2747 | 0 | if (newProcesses.Count == 1) { |
2748 | | /* Install our handler for SIGCHLD. Repeat call until it is not |
2749 | | interrupted. */ |
2750 | 0 | struct sigaction newSigAction; |
2751 | 0 | memset(&newSigAction, 0, sizeof(struct sigaction)); |
2752 | 0 | #if KWSYSPE_USE_SIGINFO |
2753 | 0 | newSigAction.sa_sigaction = kwsysProcessesSignalHandler; |
2754 | 0 | newSigAction.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; |
2755 | 0 | # ifdef SA_RESTART |
2756 | 0 | newSigAction.sa_flags |= SA_RESTART; |
2757 | 0 | # endif |
2758 | | #else |
2759 | | newSigAction.sa_handler = kwsysProcessesSignalHandler; |
2760 | | newSigAction.sa_flags = SA_NOCLDSTOP; |
2761 | | #endif |
2762 | 0 | sigemptyset(&newSigAction.sa_mask); |
2763 | 0 | while ((sigaction(SIGCHLD, &newSigAction, |
2764 | 0 | &kwsysProcessesOldSigChldAction) < 0) && |
2765 | 0 | (errno == EINTR)) { |
2766 | 0 | } |
2767 | | |
2768 | | /* Install our handler for SIGINT / SIGTERM. Repeat call until |
2769 | | it is not interrupted. */ |
2770 | 0 | sigemptyset(&newSigAction.sa_mask); |
2771 | 0 | sigaddset(&newSigAction.sa_mask, SIGTERM); |
2772 | 0 | while ((sigaction(SIGINT, &newSigAction, |
2773 | 0 | &kwsysProcessesOldSigIntAction) < 0) && |
2774 | 0 | (errno == EINTR)) { |
2775 | 0 | } |
2776 | |
|
2777 | 0 | sigemptyset(&newSigAction.sa_mask); |
2778 | 0 | sigaddset(&newSigAction.sa_mask, SIGINT); |
2779 | 0 | while ((sigaction(SIGTERM, &newSigAction, |
2780 | 0 | &kwsysProcessesOldSigIntAction) < 0) && |
2781 | 0 | (errno == EINTR)) { |
2782 | 0 | } |
2783 | 0 | } |
2784 | 0 | } |
2785 | | |
2786 | 0 | return 1; |
2787 | 0 | } |
2788 | | |
2789 | | static void kwsysProcessesRemove(kwsysProcess* cp) |
2790 | 0 | { |
2791 | | /* Attempt to remove the given signal pipe from the signal handler set. */ |
2792 | 0 | { |
2793 | | /* Find the given process in the set. */ |
2794 | 0 | kwsysProcessInstances newProcesses = kwsysProcesses; |
2795 | 0 | int i; |
2796 | 0 | for (i = 0; i < newProcesses.Count; ++i) { |
2797 | 0 | if (newProcesses.Processes[i] == cp) { |
2798 | 0 | break; |
2799 | 0 | } |
2800 | 0 | } |
2801 | 0 | if (i < newProcesses.Count) { |
2802 | | /* Remove the process from the set. */ |
2803 | 0 | --newProcesses.Count; |
2804 | 0 | for (; i < newProcesses.Count; ++i) { |
2805 | 0 | newProcesses.Processes[i] = newProcesses.Processes[i + 1]; |
2806 | 0 | } |
2807 | | |
2808 | | /* If this was the last process, disable the signal handler. */ |
2809 | 0 | if (newProcesses.Count == 0) { |
2810 | | /* Restore the signal handlers. Repeat call until it is not |
2811 | | interrupted. */ |
2812 | 0 | while ((sigaction(SIGCHLD, &kwsysProcessesOldSigChldAction, 0) < 0) && |
2813 | 0 | (errno == EINTR)) { |
2814 | 0 | } |
2815 | 0 | while ((sigaction(SIGINT, &kwsysProcessesOldSigIntAction, 0) < 0) && |
2816 | 0 | (errno == EINTR)) { |
2817 | 0 | } |
2818 | 0 | while ((sigaction(SIGTERM, &kwsysProcessesOldSigTermAction, 0) < 0) && |
2819 | 0 | (errno == EINTR)) { |
2820 | 0 | } |
2821 | | |
2822 | | /* Free the table of process pointers since it is now empty. |
2823 | | This is safe because the signal handler has been removed. */ |
2824 | 0 | newProcesses.Size = 0; |
2825 | 0 | free(newProcesses.Processes); |
2826 | 0 | newProcesses.Processes = 0; |
2827 | 0 | } |
2828 | | |
2829 | | /* Store the new set in that seen by the signal handler. */ |
2830 | 0 | kwsysProcessesUpdate(&newProcesses); |
2831 | 0 | } |
2832 | 0 | } |
2833 | | |
2834 | | /* Close the pipe through which the signal handler may have notified |
2835 | | the given process object that a child has exited. */ |
2836 | 0 | kwsysProcessCleanupDescriptor(&cp->SignalPipe); |
2837 | 0 | } |
2838 | | |
2839 | | static void kwsysProcessesSignalHandler(int signum |
2840 | | #if KWSYSPE_USE_SIGINFO |
2841 | | , |
2842 | | siginfo_t* info, void* ucontext |
2843 | | #endif |
2844 | | ) |
2845 | 0 | { |
2846 | 0 | int i; |
2847 | 0 | int j; |
2848 | 0 | int procStatus; |
2849 | 0 | int old_errno = errno; |
2850 | 0 | #if KWSYSPE_USE_SIGINFO |
2851 | 0 | (void)info; |
2852 | 0 | (void)ucontext; |
2853 | 0 | #endif |
2854 | | |
2855 | | /* Signal all process objects that a child has terminated. */ |
2856 | 0 | switch (signum) { |
2857 | 0 | default: |
2858 | 0 | break; |
2859 | 0 | case SIGCHLD: |
2860 | 0 | for (i = 0; i < kwsysProcesses.Count; ++i) { |
2861 | | /* Set the pipe in a signalled state. */ |
2862 | 0 | char buf = 1; |
2863 | 0 | kwsysProcess* cp = kwsysProcesses.Processes[i]; |
2864 | 0 | kwsysProcess_ssize_t pipeStatus = |
2865 | 0 | read(cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL], &buf, 1); |
2866 | 0 | (void)pipeStatus; |
2867 | 0 | pipeStatus = write(cp->SignalPipe, &buf, 1); |
2868 | 0 | (void)pipeStatus; |
2869 | 0 | } |
2870 | 0 | break; |
2871 | 0 | case SIGINT: |
2872 | 0 | case SIGTERM: |
2873 | | /* Signal child processes that are running in new process groups. */ |
2874 | 0 | for (i = 0; i < kwsysProcesses.Count; ++i) { |
2875 | 0 | kwsysProcess* cp = kwsysProcesses.Processes[i]; |
2876 | | /* Check Killed to avoid data race condition when killing. |
2877 | | Check State to avoid data race condition in kwsysProcessCleanup |
2878 | | when there is an error (it leaves a reaped PID). */ |
2879 | 0 | if (cp->CreateProcessGroup && !cp->Killed && |
2880 | 0 | cp->State != kwsysProcess_State_Error && cp->ForkPIDs) { |
2881 | 0 | for (j = 0; j < cp->NumberOfCommands; ++j) { |
2882 | | /* Make sure the PID is still valid. */ |
2883 | 0 | if (cp->ForkPIDs[j]) { |
2884 | | /* The user created a process group for this process. The group |
2885 | | ID |
2886 | | is the process ID for the original process in the group. */ |
2887 | 0 | kill(-cp->ForkPIDs[j], SIGINT); |
2888 | 0 | } |
2889 | 0 | } |
2890 | 0 | } |
2891 | 0 | } |
2892 | | |
2893 | | /* Wait for all processes to terminate. */ |
2894 | 0 | while (wait(&procStatus) >= 0 || errno != ECHILD) { |
2895 | 0 | } |
2896 | | |
2897 | | /* Terminate the process, which is now in an inconsistent state |
2898 | | because we reaped all the PIDs that it may have been reaping |
2899 | | or may have reaped in the future. Reraise the signal so that |
2900 | | the proper exit code is returned. */ |
2901 | 0 | { |
2902 | | /* Install default signal handler. */ |
2903 | 0 | struct sigaction defSigAction; |
2904 | 0 | sigset_t unblockSet; |
2905 | 0 | memset(&defSigAction, 0, sizeof(defSigAction)); |
2906 | 0 | defSigAction.sa_handler = SIG_DFL; |
2907 | 0 | sigemptyset(&defSigAction.sa_mask); |
2908 | 0 | while ((sigaction(signum, &defSigAction, 0) < 0) && (errno == EINTR)) { |
2909 | 0 | } |
2910 | | /* Unmask the signal. */ |
2911 | 0 | sigemptyset(&unblockSet); |
2912 | 0 | sigaddset(&unblockSet, signum); |
2913 | 0 | sigprocmask(SIG_UNBLOCK, &unblockSet, 0); |
2914 | | /* Raise the signal again. */ |
2915 | 0 | raise(signum); |
2916 | | /* We shouldn't get here... but if we do... */ |
2917 | 0 | _exit(1); |
2918 | 0 | } |
2919 | | /* break omitted to silence unreachable code clang compiler warning. */ |
2920 | 0 | } |
2921 | | |
2922 | | #if !KWSYSPE_USE_SIGINFO |
2923 | | /* Re-Install our handler. Repeat call until it is not interrupted. */ |
2924 | | { |
2925 | | struct sigaction newSigAction; |
2926 | | struct sigaction* oldSigAction; |
2927 | | memset(&newSigAction, 0, sizeof(struct sigaction)); |
2928 | | newSigAction.sa_handler = kwsysProcessesSignalHandler; |
2929 | | newSigAction.sa_flags = SA_NOCLDSTOP; |
2930 | | sigemptyset(&newSigAction.sa_mask); |
2931 | | switch (signum) { |
2932 | | case SIGCHLD: |
2933 | | oldSigAction = &kwsysProcessesOldSigChldAction; |
2934 | | break; |
2935 | | case SIGINT: |
2936 | | sigaddset(&newSigAction.sa_mask, SIGTERM); |
2937 | | oldSigAction = &kwsysProcessesOldSigIntAction; |
2938 | | break; |
2939 | | case SIGTERM: |
2940 | | sigaddset(&newSigAction.sa_mask, SIGINT); |
2941 | | oldSigAction = &kwsysProcessesOldSigTermAction; |
2942 | | break; |
2943 | | default: |
2944 | | return; |
2945 | | } |
2946 | | while ((sigaction(signum, &newSigAction, oldSigAction) < 0) && |
2947 | | (errno == EINTR)) |
2948 | | ; |
2949 | | } |
2950 | | #endif |
2951 | | |
2952 | 0 | errno = old_errno; |
2953 | 0 | } |
2954 | | |
2955 | | void kwsysProcess_ResetStartTime(kwsysProcess* cp) |
2956 | 0 | { |
2957 | 0 | if (!cp) { |
2958 | 0 | return; |
2959 | 0 | } |
2960 | | /* Reset start time. */ |
2961 | 0 | cp->StartTime = kwsysProcessTimeGetCurrent(); |
2962 | 0 | } |