57
56
/* All processes. */
58
57
static struct list all_processes = LIST_INITIALIZER(&all_processes);
60
static bool sigchld_is_blocked(void);
61
static void block_sigchld(sigset_t *);
62
static void unblock_sigchld(const sigset_t *);
63
59
static void sigchld_handler(int signr OVS_UNUSED);
64
static bool is_member(int x, const int *array, size_t);
66
61
/* Initializes the process subsystem (if it is not already initialized). Calls
67
62
* exit() if initialization fails.
64
* This function may not be called after creating any additional threads.
69
66
* Calling this function is optional; it will be called automatically by
70
67
* process_start() if necessary. Calling it explicitly allows the client to
71
68
* prevent the process from exiting at an unexpected time. */
175
168
* argv[0] is used as the name of the process. Searches the PATH environment
176
169
* variable to find the program to execute.
171
* This function may not be called after creating any additional threads.
178
173
* All file descriptors are closed before executing the subprocess, except for
179
* fds 0, 1, and 2 and the 'n_keep_fds' fds listed in 'keep_fds'. Also, any of
180
* the 'n_null_fds' fds listed in 'null_fds' are replaced by /dev/null.
182
176
* Returns 0 if successful, otherwise a positive errno value indicating the
183
177
* error. If successful, '*pp' is assigned a new struct process that may be
184
178
* used to query the process's status. On failure, '*pp' is set to NULL. */
186
process_start(char **argv,
187
const int keep_fds[], size_t n_keep_fds,
188
const int null_fds[], size_t n_null_fds,
180
process_start(char **argv, struct process **pp)
185
assert_single_threaded();
197
188
COVERAGE_INC(process_start);
198
189
error = process_prestart(argv);
228
207
fatal_signal_fork();
229
unblock_sigchld(&oldsigs);
230
for (fd = 0; fd < fd_max; fd++) {
231
if (is_member(fd, null_fds, n_null_fds)) {
233
} else if (fd >= 3 && fd != nullfd
234
&& !is_member(fd, keep_fds, n_keep_fds)) {
239
&& !is_member(nullfd, keep_fds, n_keep_fds)
240
&& !is_member(nullfd, null_fds, n_null_fds)) {
208
for (fd = 3; fd < fd_max; fd++) {
243
211
execvp(argv[0], argv);
244
212
fprintf(stderr, "execvp(\"%s\") failed: %s\n",
245
argv[0], strerror(errno));
213
argv[0], ovs_strerror(errno));
311
268
return p->status;
315
process_run(char **argv,
316
const int keep_fds[], size_t n_keep_fds,
317
const int null_fds[], size_t n_null_fds,
323
COVERAGE_INC(process_run);
324
retval = process_start(argv, keep_fds, n_keep_fds, null_fds, n_null_fds,
331
while (!process_exited(p)) {
335
*status = process_status(p);
340
271
/* Given 'status', which is a process status in the form reported by waitpid(2)
341
272
* and returned by process_status(), returns a string describing how the
342
273
* process terminated. The caller is responsible for freeing the string when
348
279
if (WIFEXITED(status)) {
349
280
ds_put_format(&ds, "exit status %d", WEXITSTATUS(status));
350
281
} else if (WIFSIGNALED(status)) {
351
ds_put_format(&ds, "killed (%s)", signal_name(WTERMSIG(status)));
282
char namebuf[SIGNAL_NAME_BUFSIZE];
284
ds_put_format(&ds, "killed (%s)",
285
signal_name(WTERMSIG(status), namebuf, sizeof namebuf));
352
286
} else if (WIFSTOPPED(status)) {
353
ds_put_format(&ds, "stopped (%s)", signal_name(WSTOPSIG(status)));
287
char namebuf[SIGNAL_NAME_BUFSIZE];
289
ds_put_format(&ds, "stopped (%s)",
290
signal_name(WSTOPSIG(status), namebuf, sizeof namebuf));
355
292
ds_put_format(&ds, "terminated abnormally (%x)", status);
400
/* process_run_capture() and supporting functions. */
409
stream_open(struct stream *s, size_t max_size)
413
s->max_size = max_size;
416
VLOG_WARN("failed to create pipe: %s", strerror(errno));
419
error = set_nonblocking(s->fds[0]);
428
stream_read(struct stream *s)
439
error = read_fully(s->fds[0], buffer, sizeof buffer, &n);
440
ds_put_buffer(&s->log, buffer, n);
442
if (error == EAGAIN || error == EWOULDBLOCK) {
446
VLOG_WARN("error reading subprocess pipe: %s",
451
} else if (s->log.length > s->max_size) {
452
VLOG_WARN("subprocess output overflowed %zu-byte buffer",
462
stream_wait(struct stream *s)
464
if (s->fds[0] >= 0) {
465
poll_fd_wait(s->fds[0], POLLIN);
470
stream_close(struct stream *s)
473
if (s->fds[0] >= 0) {
476
if (s->fds[1] >= 0) {
481
/* Starts the process whose arguments are given in the null-terminated array
482
* 'argv' and waits for it to exit. On success returns 0 and stores the
483
* process exit value (suitable for passing to process_status_msg()) in
484
* '*status'. On failure, returns a positive errno value and stores 0 in
487
* If 'stdout_log' is nonnull, then the subprocess's output to stdout (up to a
488
* limit of 'log_max' bytes) is captured in a memory buffer, which
489
* when this function returns 0 is stored as a null-terminated string in
490
* '*stdout_log'. The caller is responsible for freeing '*stdout_log' (by
491
* passing it to free()). When this function returns an error, '*stdout_log'
494
* If 'stderr_log' is nonnull, then it is treated like 'stdout_log' except
495
* that it captures the subprocess's output to stderr. */
497
process_run_capture(char **argv, char **stdout_log, char **stderr_log,
498
size_t max_log, int *status)
500
struct stream s_stdout, s_stderr;
505
COVERAGE_INC(process_run_capture);
513
error = process_prestart(argv);
518
error = stream_open(&s_stdout, max_log);
523
error = stream_open(&s_stderr, max_log);
525
stream_close(&s_stdout);
529
block_sigchld(&oldsigs);
534
unblock_sigchld(&oldsigs);
535
VLOG_WARN("fork failed: %s", strerror(error));
537
stream_close(&s_stdout);
538
stream_close(&s_stderr);
542
/* Running in parent process. */
545
p = process_register(argv[0], pid);
546
unblock_sigchld(&oldsigs);
548
close(s_stdout.fds[1]);
549
close(s_stderr.fds[1]);
550
while (!process_exited(p)) {
551
stream_read(&s_stdout);
552
stream_read(&s_stderr);
554
stream_wait(&s_stdout);
555
stream_wait(&s_stderr);
559
stream_read(&s_stdout);
560
stream_read(&s_stderr);
563
*stdout_log = ds_steal_cstr(&s_stdout.log);
566
*stderr_log = ds_steal_cstr(&s_stderr.log);
569
stream_close(&s_stdout);
570
stream_close(&s_stderr);
572
*status = process_status(p);
576
/* Running in child process. */
581
unblock_sigchld(&oldsigs);
583
dup2(get_null_fd(), 0);
584
dup2(s_stdout.fds[1], 1);
585
dup2(s_stderr.fds[1], 2);
587
max_fds = get_max_fds();
588
for (i = 3; i < max_fds; i++) {
592
execvp(argv[0], argv);
593
fprintf(stderr, "execvp(\"%s\") failed: %s\n",
594
argv[0], strerror(errno));
600
367
sigchld_handler(int signr OVS_UNUSED)
604
COVERAGE_INC(process_sigchld);
605
LIST_FOR_EACH (p, node, &all_processes) {
609
retval = waitpid(p->pid, &status, WNOHANG);
610
} while (retval == -1 && errno == EINTR);
611
if (retval == p->pid) {
614
} else if (retval < 0) {
615
/* XXX We want to log something but we're in a signal
622
369
ignore(write(fds[1], "", 1));
626
is_member(int x, const int *array, size_t n)
630
for (i = 0; i < n; i++) {
639
sigchld_is_blocked(void)
643
xsigprocmask(SIG_SETMASK, NULL, &sigs);
644
return sigismember(&sigs, SIGCHLD);
648
block_sigchld(sigset_t *oldsigs)
652
sigemptyset(&sigchld);
653
sigaddset(&sigchld, SIGCHLD);
654
xsigprocmask(SIG_BLOCK, &sigchld, oldsigs);
658
unblock_sigchld(const sigset_t *oldsigs)
660
xsigprocmask(SIG_SETMASK, oldsigs, NULL);