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;
34 /* Internal data type for process handling
36 * Allocation: these structures may have multiple references:
37 * - from the original ctx pointer
38 * - due to inclusion in async_list
39 * - due to a currently-registered waiter
44 /* prevent talloc_free(process) from working */
47 struct process process;
48 struct list_item async_list;
50 struct waiter *stdout_waiter;
55 static struct procset *procset;
57 static struct process_info *get_info(struct process *process)
59 return container_of(process, struct process_info, process);
62 /* Read as much as possible into the currently-allocated stdout buffer, and
63 * possibly realloc it for the next read */
64 static int process_read_stdout_once(struct process_info *procinfo)
66 struct process *process = &procinfo->process;
69 assert(process->keep_stdout);
71 fd = procinfo->stdout_pipe[0];
73 max_len = procinfo->stdout_buf_len - process->stdout_len - 1;
75 rc = read(fd, process->stdout_buf + process->stdout_len, max_len);
79 process->stdout_len += rc;
80 if (process->stdout_len == procinfo->stdout_buf_len - 1) {
81 procinfo->stdout_buf_len *= 2;
82 process->stdout_buf = talloc_realloc(procinfo,
83 process->stdout_buf, char,
84 procinfo->stdout_buf_len);
90 static int process_setup_stdout_pipe(struct process_info *procinfo)
94 if (!procinfo->process.keep_stdout)
97 procinfo->stdout_buf_len = 4096;
98 procinfo->process.stdout_len = 0;
99 procinfo->process.stdout_buf = talloc_array(procinfo, char,
100 procinfo->stdout_buf_len);
102 rc = pipe(procinfo->stdout_pipe);
104 pb_log("pipe failed");
110 static void process_setup_stdout_parent(struct process_info *procinfo)
112 if (!procinfo->process.keep_stdout)
115 close(procinfo->stdout_pipe[1]);
118 static void process_setup_stdout_child(struct process_info *procinfo)
120 int log = fileno(pb_log_get_stream());
122 if (procinfo->process.keep_stdout)
123 dup2(procinfo->stdout_pipe[1], STDOUT_FILENO);
125 dup2(log, STDOUT_FILENO);
127 dup2(log, STDERR_FILENO);
130 static void process_finish_stdout(struct process_info *procinfo)
132 close(procinfo->stdout_pipe[0]);
133 procinfo->process.stdout_buf[procinfo->process.stdout_len] = '\0';
136 static int process_read_stdout(struct process_info *procinfo)
140 if (!procinfo->process.keep_stdout)
144 rc = process_read_stdout_once(procinfo);
147 process_finish_stdout(procinfo);
149 return rc < 0 ? rc : 0;
152 static int process_stdout_cb(void *arg)
154 struct process_info *procinfo = arg;
157 rc = process_read_stdout_once(procinfo);
159 /* if we're going to signal to the waitset that we're done (ie, non-zero
160 * return value), then the waiters will remove us, so we drop the
163 talloc_unlink(procset, procinfo);
164 procinfo->stdout_waiter = NULL;
173 static void sigchld_sigaction(int signo, siginfo_t *info,
174 void *arg __attribute__((unused)))
179 if (signo != SIGCHLD)
184 rc = write(procset->sigchld_pipe[1], &pid, sizeof(pid));
185 if (rc != sizeof(pid))
186 pb_log("%s: write failed: %s\n", __func__, strerror(errno));
189 static int sigchld_pipe_event(void *arg)
191 struct process_info *procinfo;
192 struct procset *procset = arg;
193 struct process *process;
196 rc = read(procset->sigchld_pipe[0], &pid, sizeof(pid));
197 if (rc != sizeof(pid))
201 list_for_each_entry(&procset->async_list, procinfo, async_list) {
202 if (procinfo->process.pid == pid) {
203 process = &procinfo->process;
208 /* We'll receive SIGCHLD for synchronous processes too; just ignore */
212 rc = waitpid(process->pid, &process->exit_status, WNOHANG);
214 /* if the process is still running, ignore the event. We leave
215 * the process in async_list so we can manage the final signal */
219 /* ensure we have all of the child's stdout */
220 process_read_stdout(procinfo);
222 if (process->exit_cb)
223 process->exit_cb(process);
225 list_remove(&procinfo->async_list);
226 talloc_unlink(procset, procinfo);
231 static int process_fini(void *p)
233 struct procset *procset = p;
236 memset(&sa, 0, sizeof(sa));
237 sa.sa_handler = SIG_DFL;
239 sigaction(SIGCHLD, &sa, NULL);
241 waiter_remove(procset->sigchld_waiter);
243 close(procset->sigchld_pipe[0]);
244 close(procset->sigchld_pipe[1]);
248 struct procset *process_init(void *ctx, struct waitset *set)
253 procset = talloc(ctx, struct procset);
254 procset->waitset = set;
255 list_init(&procset->async_list);
257 rc = pipe(procset->sigchld_pipe);
259 pb_log("%s: pipe() failed: %s\n", __func__, strerror(errno));
263 procset->sigchld_waiter = waiter_register_io(set,
264 procset->sigchld_pipe[0], WAIT_IN,
265 sigchld_pipe_event, procset);
266 if (!procset->sigchld_waiter)
269 memset(&sa, 0, sizeof(sa));
270 sa.sa_sigaction = sigchld_sigaction;
271 sa.sa_flags = SA_SIGINFO | SA_NOCLDSTOP;
273 rc = sigaction(SIGCHLD, &sa, NULL);
275 pb_log("%s: sigaction() failed: %s\n", __func__,
280 talloc_set_destructor(procset, process_fini);
285 waiter_remove(procset->sigchld_waiter);
287 close(procset->sigchld_pipe[0]);
288 close(procset->sigchld_pipe[1]);
290 talloc_free(procset);
294 struct process *process_create(void *ctx)
296 struct process_info *info = talloc_zero(ctx, struct process_info);
297 info->orig_ctx = ctx;
298 return &info->process;
301 void process_release(struct process *process)
303 struct process_info *info = get_info(process);
304 talloc_unlink(info->orig_ctx, info);
307 static int process_run_common(struct process_info *procinfo)
309 struct process *process = &procinfo->process;
315 logmsg = talloc_asprintf(procinfo, " exe: %s\n argv:", process->path);
316 for (i = 0, arg = process->argv[i]; arg; i++, arg = process->argv[i])
317 logmsg = talloc_asprintf_append(logmsg, " '%s'", arg);
319 pb_log("Running command:\n%s\n", logmsg);
321 rc = process_setup_stdout_pipe(procinfo);
327 pb_log("%s: fork failed: %s\n", __func__, strerror(errno));
332 process_setup_stdout_child(procinfo);
333 execvp(process->path, (char * const *)process->argv);
337 process_setup_stdout_parent(procinfo);
343 int process_run_sync(struct process *process)
345 struct process_info *procinfo = get_info(process);
348 rc = process_run_common(procinfo);
352 process_read_stdout(procinfo);
354 rc = waitpid(process->pid, &process->exit_status, 0);
356 pb_log("%s: waitpid failed: %s\n", __func__, strerror(errno));
363 int process_run_async(struct process *process)
365 struct process_info *procinfo = get_info(process);
368 rc = process_run_common(procinfo);
372 if (process->keep_stdout) {
373 procinfo->stdout_waiter = waiter_register_io(procset->waitset,
374 procinfo->stdout_pipe[0],
375 WAIT_IN, process_stdout_cb,
377 talloc_reference(procset, procinfo);
380 list_add(&procset->async_list, &procinfo->async_list);
381 talloc_reference(procset, procinfo);
386 void process_stop_async(struct process *process)
388 kill(process->pid, SIGTERM);
391 int process_run_simple_argv(void *ctx, const char *argv[])
393 struct process *process;
396 process = process_create(ctx);
398 process->path = argv[0];
399 process->argv = argv;
401 rc = process_run_sync(process);
404 rc = process->exit_status;
406 process_release(process);
411 int process_run_simple(void *ctx, const char *name, ...)
413 int rc, i, n_argv = 1;
418 while (va_arg(ap, char *))
422 argv = talloc_array(ctx, const char *, n_argv + 1);
426 for (i = 1; i < n_argv; i++)
427 argv[i] = va_arg(ap, const char *);
432 rc = process_run_simple_argv(ctx, argv);