1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30 #include <sys/types.h>
36 #if defined(__APPLE__) && !TARGET_OS_IPHONE
37 # include <crt_externs.h>
38 # define environ (*_NSGetEnviron())
40 extern char **environ;
44 static ngx_queue_t* uv__process_queue(uv_loop_t* loop, int pid) {
46 return loop->process_handles + pid % ARRAY_SIZE(loop->process_handles);
50 static uv_process_t* uv__process_find(uv_loop_t* loop, int pid) {
55 h = uv__process_queue(loop, pid);
57 ngx_queue_foreach(q, h) {
58 handle = ngx_queue_data(q, uv_process_t, queue);
59 if (handle->pid == pid) return handle;
66 static void uv__chld(uv_signal_t* handle, int signum) {
67 uv_process_t* process;
73 assert(signum == SIGCHLD);
77 pid = waitpid(-1, &status, WNOHANG);
78 while (pid == -1 && errno == EINTR);
85 return; /* XXX stop signal watcher? */
90 process = uv__process_find(handle->loop, pid);
92 continue; /* XXX bug? abort? */
94 uv__handle_stop(process);
96 if (process->exit_cb == NULL)
102 if (WIFEXITED(status))
103 exit_status = WEXITSTATUS(status);
105 if (WIFSIGNALED(status))
106 term_signal = WTERMSIG(status);
108 if (process->errorno) {
109 uv__set_sys_error(process->loop, process->errorno);
110 exit_status = -1; /* execve() failed */
113 process->exit_cb(process, exit_status, term_signal);
118 int uv__make_socketpair(int fds[2], int flags) {
119 #if defined(__linux__)
120 static int no_cloexec;
125 if (socketpair(AF_UNIX, SOCK_STREAM | UV__SOCK_CLOEXEC | flags, 0, fds) == 0)
128 /* Retry on EINVAL, it means SOCK_CLOEXEC is not supported.
129 * Anything else is a genuine error.
139 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
142 uv__cloexec(fds[0], 1);
143 uv__cloexec(fds[1], 1);
145 if (flags & UV__F_NONBLOCK) {
146 uv__nonblock(fds[0], 1);
147 uv__nonblock(fds[1], 1);
154 int uv__make_pipe(int fds[2], int flags) {
155 #if defined(__linux__)
161 if (uv__pipe2(fds, flags | UV__O_CLOEXEC) == 0)
175 uv__cloexec(fds[0], 1);
176 uv__cloexec(fds[1], 1);
178 if (flags & UV__F_NONBLOCK) {
179 uv__nonblock(fds[0], 1);
180 uv__nonblock(fds[1], 1);
188 * Used for initializing stdio streams like options.stdin_stream. Returns
189 * zero on success. See also the cleanup section in uv_spawn().
191 static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
195 mask = UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM;
197 switch (container->flags & mask) {
202 assert(container->data.stream != NULL);
203 if (container->data.stream->type != UV_NAMED_PIPE) {
207 return uv__make_socketpair(fds, 0);
210 case UV_INHERIT_STREAM:
211 if (container->flags & UV_INHERIT_FD)
212 fd = container->data.fd;
214 fd = uv__stream_fd(container->data.stream);
225 assert(0 && "Unexpected flags");
231 static int uv__process_open_stream(uv_stdio_container_t* container,
236 if (!(container->flags & UV_CREATE_PIPE) || pipefds[0] < 0)
239 if (close(pipefds[1]))
240 if (errno != EINTR && errno != EINPROGRESS)
244 uv__nonblock(pipefds[0], 1);
246 if (container->data.stream->type == UV_NAMED_PIPE &&
247 ((uv_pipe_t*)container->data.stream)->ipc)
248 flags = UV_STREAM_READABLE | UV_STREAM_WRITABLE;
250 flags = UV_STREAM_WRITABLE;
252 flags = UV_STREAM_READABLE;
254 return uv__stream_open(container->data.stream, pipefds[0], flags);
258 static void uv__process_close_stream(uv_stdio_container_t* container) {
259 if (!(container->flags & UV_CREATE_PIPE)) return;
260 uv__stream_close((uv_stream_t*)container->data.stream);
264 static void uv__write_int(int fd, int val) {
268 n = write(fd, &val, sizeof(val));
269 while (n == -1 && errno == EINTR);
271 if (n == -1 && errno == EPIPE)
272 return; /* parent process has quit */
274 assert(n == sizeof(val));
278 static void uv__process_child_init(uv_process_options_t options,
286 if (options.flags & UV_PROCESS_DETACHED)
289 for (fd = 0; fd < stdio_count; fd++) {
290 close_fd = pipes[fd][0];
291 use_fd = pipes[fd][1];
298 /* redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is
301 use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR);
304 uv__write_int(error_fd, errno);
305 perror("failed to open stdio");
311 uv__cloexec(use_fd, 0);
321 if (options.cwd && chdir(options.cwd)) {
322 uv__write_int(error_fd, errno);
327 if ((options.flags & UV_PROCESS_SETGID) && setgid(options.gid)) {
328 uv__write_int(error_fd, errno);
333 if ((options.flags & UV_PROCESS_SETUID) && setuid(options.uid)) {
334 uv__write_int(error_fd, errno);
340 environ = options.env;
343 execvp(options.file, options.args);
344 uv__write_int(error_fd, errno);
350 int uv_spawn(uv_loop_t* loop,
351 uv_process_t* process,
352 const uv_process_options_t options) {
353 int signal_pipe[2] = { -1, -1 };
361 assert(options.file != NULL);
362 assert(!(options.flags & ~(UV_PROCESS_DETACHED |
365 UV_PROCESS_WINDOWS_HIDE |
366 UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
368 uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
369 ngx_queue_init(&process->queue);
371 stdio_count = options.stdio_count;
375 pipes = malloc(stdio_count * sizeof(*pipes));
381 for (i = 0; i < stdio_count; i++) {
386 for (i = 0; i < options.stdio_count; i++)
387 if (uv__process_init_stdio(options.stdio + i, pipes[i]))
390 /* This pipe is used by the parent to wait until
391 * the child has called `execve()`. We need this
392 * to avoid the following race condition:
394 * if ((pid = fork()) > 0) {
395 * kill(pid, SIGTERM);
397 * else if (pid == 0) {
398 * execve("/bin/cat", argp, envp);
401 * The parent sends a signal immediately after forking.
402 * Since the child may not have called `execve()` yet,
403 * there is no telling what process receives the signal,
404 * our fork or /bin/cat.
406 * To avoid ambiguity, we create a pipe with both ends
407 * marked close-on-exec. Then, after the call to `fork()`,
408 * the parent polls the read end until it EOFs or errors with EPIPE.
410 if (uv__make_pipe(signal_pipe, 0))
413 uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD);
418 close(signal_pipe[0]);
419 close(signal_pipe[1]);
424 uv__process_child_init(options, stdio_count, pipes, signal_pipe[1]);
428 close(signal_pipe[1]);
430 process->errorno = 0;
432 r = read(signal_pipe[0], &process->errorno, sizeof(process->errorno));
433 while (r == -1 && errno == EINTR);
437 else if (r == sizeof(process->errorno))
438 ; /* okay, read errorno */
439 else if (r == -1 && errno == EPIPE)
440 ; /* okay, got EPIPE */
444 close(signal_pipe[0]);
446 for (i = 0; i < options.stdio_count; i++) {
447 if (uv__process_open_stream(options.stdio + i, pipes[i], i == 0)) {
448 while (i--) uv__process_close_stream(options.stdio + i);
453 q = uv__process_queue(loop, pid);
454 ngx_queue_insert_tail(q, &process->queue);
457 process->exit_cb = options.exit_cb;
458 uv__handle_start(process);
464 uv__set_sys_error(process->loop, errno);
467 for (i = 0; i < stdio_count; i++) {
468 if (i < options.stdio_count)
469 if (options.stdio[i].flags & (UV_INHERIT_FD | UV_INHERIT_STREAM))
471 if (pipes[i][0] != -1)
473 if (pipes[i][1] != -1)
483 int uv_process_kill(uv_process_t* process, int signum) {
484 int r = kill(process->pid, signum);
487 uv__set_sys_error(process->loop, errno);
495 uv_err_t uv_kill(int pid, int signum) {
496 int r = kill(pid, signum);
499 return uv__new_sys_error(errno);
506 void uv__process_close(uv_process_t* handle) {
507 /* TODO stop signal watcher when this is the last handle */
508 ngx_queue_remove(&handle->queue);
509 uv__handle_stop(handle);