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