2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; version 2 of the License.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <process/process.h>
23 #include <talloc/talloc.h>
24 #include <waiter/waiter.h>
28 struct waitset *waitset;
29 struct list async_list;
31 struct waiter *sigchld_waiter;
35 /* Internal data type for process handling
37 * Allocation: these structures may have multiple references:
38 * - from the original ctx pointer
39 * - due to inclusion in async_list
40 * - due to a currently-registered waiter
45 /* prevent talloc_free(process) from working */
48 struct process process;
49 struct list_item async_list;
51 struct waiter *stdout_waiter;
57 static struct procset *procset;
59 static struct process_info *get_info(struct process *process)
61 return container_of(process, struct process_info, process);
64 struct process *procinfo_get_process(struct process_info *procinfo)
66 return &procinfo->process;
69 /* Read as much as possible into the currently-allocated stdout buffer, and
70 * possibly realloc it for the next read
71 * If the line pointer is not NULL, it is set to the start of the latest
75 * > 0 on success (even though no bytes may have been read)
76 * 0 on EOF (no error, but no more reads can be performed)
79 static int process_read_stdout_once(struct process_info *procinfo, char **line)
81 struct process *process = &procinfo->process;
84 assert(process->keep_stdout);
86 fd = procinfo->stdout_pipe[0];
88 max_len = procinfo->stdout_buf_len - process->stdout_len - 1;
90 rc = read(fd, process->stdout_buf + process->stdout_len, max_len);
96 pb_log_fn("read failed: %s\n", strerror(errno));
101 *line = process->stdout_buf + process->stdout_len;
103 process->stdout_len += rc;
104 if (process->stdout_len == procinfo->stdout_buf_len - 1) {
105 procinfo->stdout_buf_len *= 2;
106 process->stdout_buf = talloc_realloc(procinfo,
107 process->stdout_buf, char,
108 procinfo->stdout_buf_len);
114 static int process_setup_stdout_pipe(struct process_info *procinfo)
118 if (!procinfo->process.keep_stdout || procinfo->process.raw_stdout)
121 procinfo->stdout_buf_len = 4096;
122 procinfo->process.stdout_len = 0;
123 procinfo->process.stdout_buf = talloc_array(procinfo, char,
124 procinfo->stdout_buf_len);
126 rc = pipe(procinfo->stdout_pipe);
128 pb_log("pipe failed");
134 static void process_setup_stdin_parent(struct process_info *procinfo)
138 if (!procinfo->process.pipe_stdin)
141 close(procinfo->stdin_pipe[0]);
142 in = fdopen(procinfo->stdin_pipe[1], "w");
144 pb_log_fn("Failed to open stdin\n");
147 fputs(procinfo->process.pipe_stdin, in);
151 static void process_setup_stdin_child(struct process_info *procinfo)
153 if (procinfo->process.pipe_stdin) {
154 close(procinfo->stdin_pipe[1]);
155 dup2(procinfo->stdin_pipe[0], STDIN_FILENO);
158 static void process_setup_stdout_parent(struct process_info *procinfo)
160 if (!procinfo->process.keep_stdout || procinfo->process.raw_stdout)
163 close(procinfo->stdout_pipe[1]);
167 static void process_setup_stdout_child(struct process_info *procinfo)
169 int log = fileno(pb_log_get_stream());
171 if (procinfo->process.raw_stdout)
174 if (procinfo->process.keep_stdout)
175 dup2(procinfo->stdout_pipe[1], STDOUT_FILENO);
177 dup2(log, STDOUT_FILENO);
179 if (procinfo->process.keep_stdout && procinfo->process.add_stderr)
180 dup2(procinfo->stdout_pipe[1], STDERR_FILENO);
182 dup2(log, STDERR_FILENO);
185 static void process_finish_stdout(struct process_info *procinfo)
187 close(procinfo->stdout_pipe[0]);
188 procinfo->process.stdout_buf[procinfo->process.stdout_len] = '\0';
191 static int process_read_stdout(struct process_info *procinfo)
195 if (!procinfo->process.keep_stdout)
199 rc = process_read_stdout_once(procinfo, NULL);
202 process_finish_stdout(procinfo);
204 return rc < 0 ? rc : 0;
207 int process_process_stdout(struct process_info *procinfo, char **line)
211 rc = process_read_stdout_once(procinfo, line);
213 /* if we're going to signal to the waitset that we're done (ie, non-zero
214 * return value), then the waiters will remove us, so we drop the
217 talloc_unlink(procset, procinfo);
218 procinfo->stdout_waiter = NULL;
227 static void sigchld_sigaction(int signo, siginfo_t *info,
228 void *arg __attribute__((unused)))
233 if (signo != SIGCHLD)
238 rc = write(procset->sigchld_pipe[1], &pid, sizeof(pid));
239 if (rc != sizeof(pid))
240 pb_log_fn("write failed: %s\n", strerror(errno));
243 static int sigchld_pipe_event(void *arg)
245 struct process_info *procinfo;
246 struct procset *procset = arg;
247 struct process *process;
250 rc = read(procset->sigchld_pipe[0], &pid, sizeof(pid));
251 if (rc != sizeof(pid))
255 list_for_each_entry(&procset->async_list, procinfo, async_list) {
256 if (procinfo->process.pid == pid) {
257 process = &procinfo->process;
262 /* We'll receive SIGCHLD for synchronous processes too; just ignore */
266 rc = waitpid(process->pid, &process->exit_status, WNOHANG);
268 /* if the process is still running, ignore the event. We leave
269 * the process in async_list so we can manage the final signal */
273 /* ensure we have all of the child's stdout */
274 process_read_stdout(procinfo);
276 if (process->exit_cb)
277 process->exit_cb(process);
279 list_remove(&procinfo->async_list);
280 talloc_unlink(procset, procinfo);
285 static int process_fini(void *p)
287 struct procset *procset = p;
290 memset(&sa, 0, sizeof(sa));
291 sa.sa_handler = SIG_DFL;
293 sigaction(SIGCHLD, &sa, NULL);
295 waiter_remove(procset->sigchld_waiter);
297 close(procset->sigchld_pipe[0]);
298 close(procset->sigchld_pipe[1]);
302 struct procset *process_init(void *ctx, struct waitset *set, bool dry_run)
307 procset = talloc(ctx, struct procset);
308 procset->waitset = set;
309 procset->dry_run = dry_run;
310 list_init(&procset->async_list);
312 rc = pipe(procset->sigchld_pipe);
314 pb_log_fn("pipe() failed: %s\n", strerror(errno));
318 procset->sigchld_waiter = waiter_register_io(set,
319 procset->sigchld_pipe[0], WAIT_IN,
320 sigchld_pipe_event, procset);
321 if (!procset->sigchld_waiter)
324 memset(&sa, 0, sizeof(sa));
325 sa.sa_sigaction = sigchld_sigaction;
326 sa.sa_flags = SA_SIGINFO | SA_NOCLDSTOP;
328 rc = sigaction(SIGCHLD, &sa, NULL);
330 pb_log_fn("sigaction() failed: %s\n",
335 talloc_set_destructor(procset, process_fini);
340 waiter_remove(procset->sigchld_waiter);
342 close(procset->sigchld_pipe[0]);
343 close(procset->sigchld_pipe[1]);
345 talloc_free(procset);
349 struct process *process_create(void *ctx)
351 struct process_info *info = talloc_zero(ctx, struct process_info);
352 info->orig_ctx = ctx;
353 return &info->process;
356 void process_release(struct process *process)
358 struct process_info *info = get_info(process);
359 talloc_unlink(info->orig_ctx, info);
362 static int process_run_common(struct process_info *procinfo)
364 struct process *process = &procinfo->process;
370 logmsg = talloc_asprintf(procinfo, " exe: %s\n argv:", process->path);
371 for (i = 0, arg = process->argv[i]; arg; i++, arg = process->argv[i])
372 logmsg = talloc_asprintf_append(logmsg, " '%s'", arg);
374 pb_log("Running command:\n%s\n", logmsg);
376 rc = process_setup_stdout_pipe(procinfo);
379 if (procinfo->process.pipe_stdin) {
380 rc = pipe(procinfo->stdin_pipe);
387 pb_log_fn("fork failed: %s\n", strerror(errno));
392 process_setup_stdout_child(procinfo);
393 process_setup_stdin_child(procinfo);
394 if (procset->dry_run)
396 execvp(process->path, (char * const *)process->argv);
400 process_setup_stdout_parent(procinfo);
401 process_setup_stdin_parent(procinfo);
407 int process_run_sync(struct process *process)
409 struct process_info *procinfo = get_info(process);
412 rc = process_run_common(procinfo);
416 process_read_stdout(procinfo);
419 rc = waitpid(process->pid, &process->exit_status, 0);
425 pb_log_fn("waitpid failed: %s\n", strerror(errno));
432 static int process_stdout_cb(struct process_info *procinfo)
434 return process_process_stdout(procinfo, NULL);
437 int process_run_async(struct process *process)
439 struct process_info *procinfo = get_info(process);
442 rc = process_run_common(procinfo);
446 if (process->keep_stdout) {
447 waiter_cb stdout_cb = process->stdout_cb ?:
448 (waiter_cb)process_stdout_cb;
449 procinfo->stdout_waiter = waiter_register_io(procset->waitset,
450 procinfo->stdout_pipe[0],
451 WAIT_IN, stdout_cb, procinfo);
452 talloc_reference(procset, procinfo);
455 list_add(&procset->async_list, &procinfo->async_list);
456 talloc_reference(procset, procinfo);
461 void process_stop_async(struct process *process)
463 /* Avoid signalling an old pid */
464 if (process->cancelled)
467 pb_debug("process: sending SIGTERM to pid %d\n", process->pid);
468 kill(process->pid, SIGTERM);
469 process->cancelled = true;
472 void process_stop_async_all(void)
474 struct process_info *procinfo;
475 struct process *process = NULL;
477 pb_debug("process: cancelling all async jobs\n");
479 list_for_each_entry(&procset->async_list, procinfo, async_list) {
480 process = &procinfo->process;
481 /* Ignore the process completion - callbacks may use stale data */
482 process->exit_cb = NULL;
483 process->stdout_cb = NULL;
484 process_stop_async(process);
488 int process_get_stdout_argv(void *ctx, struct process_stdout **stdout,
494 p = process_create(NULL);
499 p->keep_stdout = true;
503 rc = process_run_sync(p);
508 pb_debug("%s: process_run_sync failed: %s.\n", __func__,
511 pb_debug("%s: stdout: %s\n\n", __func__, p->stdout_buf);
518 *stdout = talloc(ctx, struct process_stdout);
525 (*stdout)->len = p->stdout_len;
526 (*stdout)->buf = talloc_memdup(*stdout, p->stdout_buf,
528 (*stdout)->buf[p->stdout_len] = 0;
535 int process_get_stdout(void *ctx, struct process_stdout **stdout,
536 const char *path, ...)
538 int rc, i, n_argv = 1;
543 while (va_arg(ap, char *))
547 argv = talloc_array(ctx, const char *, n_argv + 1);
551 for (i = 1; i < n_argv; i++)
552 argv[i] = va_arg(ap, const char *);
557 rc = process_get_stdout_argv(ctx, stdout, argv);
564 bool process_exit_ok(struct process *process)
566 return WIFEXITED(process->exit_status) &&
567 WEXITSTATUS(process->exit_status) == 0;