Rizin
unix-like reverse engineering framework and cli tools
process.c File Reference
#include "uv.h"
#include "internal.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>

Go to the source code of this file.

Functions

static void uv__chld (uv_signal_t *handle, int signum)
 
static int uv__make_socketpair (int fds[2])
 
int uv__make_pipe (int fds[2], int flags)
 
static int uv__process_init_stdio (uv_stdio_container_t *container, int fds[2])
 
static int uv__process_open_stream (uv_stdio_container_t *container, int pipefds[2])
 
static void uv__process_close_stream (uv_stdio_container_t *container)
 
static void uv__write_int (int fd, int val)
 
static void uv__process_child_init (const uv_process_options_t *options, int stdio_count, int(*pipes)[2], int error_fd)
 
int uv_spawn (uv_loop_t *loop, uv_process_t *process, const uv_process_options_t *options)
 
int uv_process_kill (uv_process_t *process, int signum)
 
int uv_kill (int pid, int signum)
 
void uv__process_close (uv_process_t *handle)
 

Variables

char ** environ
 

Function Documentation

◆ uv__chld()

static void uv__chld ( uv_signal_t handle,
int  signum 
)
static

Definition at line 48 of file process.c.

48  {
50  uv_loop_t* loop;
51  int exit_status;
52  int term_signal;
53  int status;
54  pid_t pid;
55  QUEUE pending;
56  QUEUE* q;
57  QUEUE* h;
58 
59  assert(signum == SIGCHLD);
60 
61  QUEUE_INIT(&pending);
62  loop = handle->loop;
63 
64  h = &loop->process_handles;
65  q = QUEUE_HEAD(h);
66  while (q != h) {
68  q = QUEUE_NEXT(q);
69 
70  do
71  pid = waitpid(process->pid, &status, WNOHANG);
72  while (pid == -1 && errno == EINTR);
73 
74  if (pid == 0)
75  continue;
76 
77  if (pid == -1) {
78  if (errno != ECHILD)
79  abort();
80  continue;
81  }
82 
83  process->status = status;
84  QUEUE_REMOVE(&process->queue);
85  QUEUE_INSERT_TAIL(&pending, &process->queue);
86  }
87 
88  h = &pending;
89  q = QUEUE_HEAD(h);
90  while (q != h) {
92  q = QUEUE_NEXT(q);
93 
94  QUEUE_REMOVE(&process->queue);
95  QUEUE_INIT(&process->queue);
97 
98  if (process->exit_cb == NULL)
99  continue;
100 
101  exit_status = 0;
102  if (WIFEXITED(process->status))
103  exit_status = WEXITSTATUS(process->status);
104 
105  term_signal = 0;
106  if (WIFSIGNALED(process->status))
107  term_signal = WTERMSIG(process->status);
108 
109  process->exit_cb(process, exit_status, term_signal);
110  }
111  assert(QUEUE_EMPTY(&pending));
112 }
static mcore_handle handle
Definition: asm_mcore.c:8
#define NULL
Definition: cris-opc.c:27
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
Definition: sflib.h:64
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment signum
Definition: sflib.h:79
assert(limit<=UINT32_MAX/2)
#define QUEUE_DATA(ptr, type, field)
Definition: queue.h:30
#define QUEUE_EMPTY(q)
Definition: queue.h:39
#define QUEUE_NEXT(q)
Definition: queue.h:24
#define QUEUE_HEAD(q)
Definition: queue.h:42
#define QUEUE_INSERT_TAIL(h, q)
Definition: queue.h:92
#define QUEUE_INIT(q)
Definition: queue.h:45
void * QUEUE[2]
Definition: queue.h:21
#define QUEUE_REMOVE(q)
Definition: queue.h:101
#define EINTR
Definition: sftypes.h:114
#define ECHILD
Definition: sftypes.h:120
int pid_t
Definition: sftypes.h:38
#define h(i)
Definition: sha256.c:48
Definition: uv.h:1780
uv_loop_t * loop
Definition: main.c:7
static enum exit_status_type exit_status
Exit status to use. This can be changed with set_exit_status().
Definition: main.c:17
#define uv__handle_stop(h)
Definition: uv-common.h:266
uv_pipe_t queue
Definition: worker.c:9
static zip_compression_status_t process(void *ud, zip_uint8_t *data, zip_uint64_t *length)

References assert(), ECHILD, EINTR, exit_status, h, handle, loop, NULL, pid, process(), queue, QUEUE_DATA, QUEUE_EMPTY, QUEUE_HEAD, QUEUE_INIT, QUEUE_INSERT_TAIL, QUEUE_NEXT, QUEUE_REMOVE, signum, status, and uv__handle_stop.

Referenced by uv_spawn().

◆ uv__make_pipe()

int uv__make_pipe ( int  fds[2],
int  flags 
)

Definition at line 142 of file process.c.

142  {
143 #if defined(__FreeBSD__) || defined(__linux__)
144  if (pipe2(fds, flags | O_CLOEXEC))
145  return UV__ERR(errno);
146 
147  return 0;
148 #else
149  if (pipe(fds))
150  return UV__ERR(errno);
151 
152  if (uv__cloexec(fds[0], 1))
153  goto fail;
154 
155  if (uv__cloexec(fds[1], 1))
156  goto fail;
157 
158  if (flags & UV__F_NONBLOCK) {
159  if (uv__nonblock(fds[0], 1))
160  goto fail;
161 
162  if (uv__nonblock(fds[1], 1))
163  goto fail;
164  }
165 
166  return 0;
167 
168 fail:
169  uv__close(fds[0]);
170  uv__close(fds[1]);
171  return UV__ERR(errno);
172 #endif
173 }
#define O_CLOEXEC
Definition: compat.h:80
#define UV__ERR(x)
Definition: errno.h:29
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname pipe
Definition: sflib.h:73
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
int uv__close(int fd)
Definition: core.c:569
#define uv__cloexec
Definition: internal.h:169
#define UV__F_NONBLOCK
Definition: internal.h:288
#define uv__nonblock
Definition: internal.h:170
#define fail(test)
Definition: tests.h:29

References fail, flags, O_CLOEXEC, pipe, uv__cloexec, uv__close(), UV__ERR, UV__F_NONBLOCK, and uv__nonblock.

Referenced by uv__async_start(), uv__signal_global_reinit(), uv__signal_loop_once_init(), and uv_spawn().

◆ uv__make_socketpair()

static int uv__make_socketpair ( int  fds[2])
static

Definition at line 115 of file process.c.

115  {
116 #if defined(__FreeBSD__) || defined(__linux__)
117  if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fds))
118  return UV__ERR(errno);
119 
120  return 0;
121 #else
122  int err;
123 
124  if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
125  return UV__ERR(errno);
126 
127  err = uv__cloexec(fds[0], 1);
128  if (err == 0)
129  err = uv__cloexec(fds[1], 1);
130 
131  if (err != 0) {
132  uv__close(fds[0]);
133  uv__close(fds[1]);
134  return UV__ERR(errno);
135  }
136 
137  return 0;
138 #endif
139 }
static bool err
Definition: armass.c:435
#define AF_UNIX
Definition: sftypes.h:285
@ SOCK_STREAM
Definition: sftypes.h:224

References AF_UNIX, err, SOCK_STREAM, uv__cloexec, uv__close(), and UV__ERR.

Referenced by uv__process_init_stdio().

◆ uv__process_child_init()

static void uv__process_child_init ( const uv_process_options_t options,
int  stdio_count,
int(*)  pipes[2],
int  error_fd 
)
static

Definition at line 267 of file process.c.

270  {
271  sigset_t set;
272  int close_fd;
273  int use_fd;
274  int err;
275  int fd;
276  int n;
277 
278  if (options->flags & UV_PROCESS_DETACHED)
279  setsid();
280 
281  /* First duplicate low numbered fds, since it's not safe to duplicate them,
282  * they could get replaced. Example: swapping stdout and stderr; without
283  * this fd 2 (stderr) would be duplicated into fd 1, thus making both
284  * stdout and stderr go to the same fd, which was not the intention. */
285  for (fd = 0; fd < stdio_count; fd++) {
286  use_fd = pipes[fd][1];
287  if (use_fd < 0 || use_fd >= fd)
288  continue;
289  pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count);
290  if (pipes[fd][1] == -1) {
291  uv__write_int(error_fd, UV__ERR(errno));
292  _exit(127);
293  }
294  }
295 
296  for (fd = 0; fd < stdio_count; fd++) {
297  close_fd = pipes[fd][0];
298  use_fd = pipes[fd][1];
299 
300  if (use_fd < 0) {
301  if (fd >= 3)
302  continue;
303  else {
304  /* redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is
305  * set
306  */
307  use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR);
308  close_fd = use_fd;
309 
310  if (use_fd < 0) {
311  uv__write_int(error_fd, UV__ERR(errno));
312  _exit(127);
313  }
314  }
315  }
316 
317  if (fd == use_fd)
318  uv__cloexec_fcntl(use_fd, 0);
319  else
320  fd = dup2(use_fd, fd);
321 
322  if (fd == -1) {
323  uv__write_int(error_fd, UV__ERR(errno));
324  _exit(127);
325  }
326 
327  if (fd <= 2)
329 
330  if (close_fd >= stdio_count)
331  uv__close(close_fd);
332  }
333 
334  for (fd = 0; fd < stdio_count; fd++) {
335  use_fd = pipes[fd][1];
336 
337  if (use_fd >= stdio_count)
338  uv__close(use_fd);
339  }
340 
341  if (options->cwd != NULL && chdir(options->cwd)) {
342  uv__write_int(error_fd, UV__ERR(errno));
343  _exit(127);
344  }
345 
346  if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) {
347  /* When dropping privileges from root, the `setgroups` call will
348  * remove any extraneous groups. If we don't call this, then
349  * even though our uid has dropped, we may still have groups
350  * that enable us to do super-user things. This will fail if we
351  * aren't root, so don't bother checking the return value, this
352  * is just done as an optimistic privilege dropping function.
353  */
355  }
356 
357  if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) {
358  uv__write_int(error_fd, UV__ERR(errno));
359  _exit(127);
360  }
361 
362  if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) {
363  uv__write_int(error_fd, UV__ERR(errno));
364  _exit(127);
365  }
366 
367  if (options->env != NULL) {
368  environ = options->env;
369  }
370 
371  /* Reset signal disposition. Use a hard-coded limit because NSIG
372  * is not fixed on Linux: it's either 32, 34 or 64, depending on
373  * whether RT signals are enabled. We are not allowed to touch
374  * RT signal handlers, glibc uses them internally.
375  */
376  for (n = 1; n < 32; n += 1) {
377  if (n == SIGKILL || n == SIGSTOP)
378  continue; /* Can't be changed. */
379 
380 #if defined(__HAIKU__)
381  if (n == SIGKILLTHR)
382  continue; /* Can't be changed. */
383 #endif
384 
385  if (SIG_ERR != signal(n, SIG_DFL))
386  continue;
387 
388  uv__write_int(error_fd, UV__ERR(errno));
389  _exit(127);
390  }
391 
392  /* Reset signal mask. */
393  sigemptyset(&set);
394  err = pthread_sigmask(SIG_SETMASK, &set, NULL);
395 
396  if (err != 0) {
397  uv__write_int(error_fd, UV__ERR(err));
398  _exit(127);
399  }
400 
401  execvp(options->file, options->args);
402  uv__write_int(error_fd, UV__ERR(errno));
403  _exit(127);
404 }
static static fork const void static count static fd const char const char static newpath chdir
Definition: sflib.h:33
static static fork const void static count static fd const char const char static newpath const char static path const char static mode static getpid setgid
Definition: sflib.h:41
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags fcntl
Definition: sflib.h:79
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment static handler static getegid char static len static pgid const char static path dup2
Definition: sflib.h:94
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment static handler static getegid char static len static pgid const char static path static newfd static getpgrp static euid const sigset_t static mask const char static len setgroups
Definition: sflib.h:112
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment signal
Definition: sflib.h:79
int n
Definition: mipsasm.c:19
#define O_RDONLY
Definition: sftypes.h:486
#define F_DUPFD
Definition: sftypes.h:503
#define O_RDWR
Definition: sftypes.h:488
int sigset_t
Definition: sftypes.h:63
int uv__nonblock_fcntl(int fd, int set)
Definition: core.c:608
int uv__cloexec_fcntl(int fd, int set)
Definition: core.c:639
#define SAVE_ERRNO(block)
Definition: internal.h:92
static void uv__write_int(int fd, int val)
Definition: process.c:248
char ** environ
@ UV_PROCESS_SETUID
Definition: uv.h:1005
@ UV_PROCESS_SETGID
Definition: uv.h:1011
@ UV_PROCESS_DETACHED
Definition: uv.h:1025
#define SIGKILL
Definition: process.c:37
static const z80_opcode fd[]
Definition: z80_tab.h:997

References chdir, dup2, environ, err, F_DUPFD, fcntl, fd, n, NULL, O_RDONLY, O_RDWR, options, SAVE_ERRNO, setgid, setgroups, SIGKILL, signal, uv__cloexec_fcntl(), uv__close(), UV__ERR, uv__nonblock_fcntl(), uv__write_int(), UV_PROCESS_DETACHED, UV_PROCESS_SETGID, and UV_PROCESS_SETUID.

Referenced by uv_spawn().

◆ uv__process_close()

void uv__process_close ( uv_process_t handle)

Definition at line 590 of file process.c.

590  {
591  QUEUE_REMOVE(&handle->queue);
593  if (QUEUE_EMPTY(&handle->loop->process_handles))
594  uv_signal_stop(&handle->loop->child_watcher);
595 }
UV_EXTERN int uv_signal_stop(uv_signal_t *handle)
Definition: signal.c:513

References handle, QUEUE_EMPTY, QUEUE_REMOVE, uv__handle_stop, and uv_signal_stop().

Referenced by uv_close().

◆ uv__process_close_stream()

static void uv__process_close_stream ( uv_stdio_container_t container)
static

Definition at line 242 of file process.c.

242  {
243  if (!(container->flags & UV_CREATE_PIPE)) return;
244  uv__stream_close(container->data.stream);
245 }
uv_stream_t * stream
Definition: uv.h:946
uv_stdio_flags flags
Definition: uv.h:943
union uv_stdio_container_s::@397 data
void uv__stream_close(uv_stream_t *handle)
Definition: stream.c:1633
@ UV_CREATE_PIPE
Definition: uv.h:923

References uv_stdio_container_s::data, uv_stdio_container_s::flags, uv_stdio_container_s::stream, uv__stream_close(), and UV_CREATE_PIPE.

Referenced by uv_spawn().

◆ uv__process_init_stdio()

static int uv__process_init_stdio ( uv_stdio_container_t container,
int  fds[2] 
)
static

Definition at line 180 of file process.c.

180  {
181  int mask;
182  int fd;
183 
185 
186  switch (container->flags & mask) {
187  case UV_IGNORE:
188  return 0;
189 
190  case UV_CREATE_PIPE:
191  assert(container->data.stream != NULL);
192  if (container->data.stream->type != UV_NAMED_PIPE)
193  return UV_EINVAL;
194  else
195  return uv__make_socketpair(fds);
196 
197  case UV_INHERIT_FD:
198  case UV_INHERIT_STREAM:
199  if (container->flags & UV_INHERIT_FD)
200  fd = container->data.fd;
201  else
202  fd = uv__stream_fd(container->data.stream);
203 
204  if (fd == -1)
205  return UV_EINVAL;
206 
207  fds[1] = fd;
208  return 0;
209 
210  default:
211  assert(0 && "Unexpected flags");
212  return UV_EINVAL;
213  }
214 }
#define mask()
#define uv__stream_fd(handle)
Definition: internal.h:282
static int uv__make_socketpair(int fds[2])
Definition: process.c:115
@ UV_INHERIT_FD
Definition: uv.h:924
@ UV_IGNORE
Definition: uv.h:922
@ UV_INHERIT_STREAM
Definition: uv.h:925

References assert(), uv_stdio_container_s::data, fd, uv_stdio_container_s::fd, uv_stdio_container_s::flags, mask, NULL, uv_stdio_container_s::stream, uv__make_socketpair(), uv__stream_fd, UV_CREATE_PIPE, UV_IGNORE, UV_INHERIT_FD, and UV_INHERIT_STREAM.

Referenced by uv_spawn().

◆ uv__process_open_stream()

static int uv__process_open_stream ( uv_stdio_container_t container,
int  pipefds[2] 
)
static

Definition at line 217 of file process.c.

218  {
219  int flags;
220  int err;
221 
222  if (!(container->flags & UV_CREATE_PIPE) || pipefds[0] < 0)
223  return 0;
224 
225  err = uv__close(pipefds[1]);
226  if (err != 0)
227  abort();
228 
229  pipefds[1] = -1;
230  uv__nonblock(pipefds[0], 1);
231 
232  flags = 0;
233  if (container->flags & UV_WRITABLE_PIPE)
235  if (container->flags & UV_READABLE_PIPE)
237 
238  return uv__stream_open(container->data.stream, pipefds[0], flags);
239 }
int uv__stream_open(uv_stream_t *, int fd, int flags)
Definition: stream.c:406
@ UV_HANDLE_WRITABLE
Definition: uv-common.h:93
@ UV_HANDLE_READABLE
Definition: uv-common.h:92
@ UV_WRITABLE_PIPE
Definition: uv.h:933
@ UV_READABLE_PIPE
Definition: uv.h:932

References uv_stdio_container_s::data, err, flags, uv_stdio_container_s::flags, uv_stdio_container_s::stream, uv__close(), uv__nonblock, uv__stream_open(), UV_CREATE_PIPE, UV_HANDLE_READABLE, UV_HANDLE_WRITABLE, UV_READABLE_PIPE, and UV_WRITABLE_PIPE.

Referenced by uv_spawn().

◆ uv__write_int()

static void uv__write_int ( int  fd,
int  val 
)
static

Definition at line 248 of file process.c.

248  {
249  ssize_t n;
250 
251  do
252  n = write(fd, &val, sizeof(val));
253  while (n == -1 && errno == EINTR);
254 
255  if (n == -1 && errno == EPIPE)
256  return; /* parent process has quit */
257 
258  assert(n == sizeof(val));
259 }
ut16 val
Definition: armass64_const.h:6
static static fork write
Definition: sflib.h:33
#define EPIPE
Definition: sftypes.h:142
int ssize_t
Definition: sftypes.h:39

References assert(), EINTR, EPIPE, fd, n, val, and write.

Referenced by uv__process_child_init().

◆ uv_kill()

int uv_kill ( int  pid,
int  signum 
)

Definition at line 582 of file process.c.

582  {
583  if (kill(pid, signum))
584  return UV__ERR(errno);
585  else
586  return 0;
587 }
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc kill
Definition: sflib.h:64

Referenced by uv_process_kill().

◆ uv_process_kill()

int uv_process_kill ( uv_process_t process,
int  signum 
)

Definition at line 577 of file process.c.

577  {
578  return uv_kill(process->pid, signum);
579 }
int uv_kill(int pid, int signum)
Definition: process.c:582

◆ uv_spawn()

int uv_spawn ( uv_loop_t loop,
uv_process_t process,
const uv_process_options_t options 
)

Definition at line 408 of file process.c.

410  {
411 #if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)
412  /* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */
413  return UV_ENOSYS;
414 #else
415  int signal_pipe[2] = { -1, -1 };
416  int pipes_storage[8][2];
417  int (*pipes)[2];
418  int stdio_count;
419  ssize_t r;
420  pid_t pid;
421  int err;
422  int exec_errorno;
423  int i;
424  int status;
425 
426  assert(options->file != NULL);
427  assert(!(options->flags & ~(UV_PROCESS_DETACHED |
434 
435  uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
436  QUEUE_INIT(&process->queue);
437 
438  stdio_count = options->stdio_count;
439  if (stdio_count < 3)
440  stdio_count = 3;
441 
442  err = UV_ENOMEM;
443  pipes = pipes_storage;
444  if (stdio_count > (int) ARRAY_SIZE(pipes_storage))
445  pipes = uv__malloc(stdio_count * sizeof(*pipes));
446 
447  if (pipes == NULL)
448  goto error;
449 
450  for (i = 0; i < stdio_count; i++) {
451  pipes[i][0] = -1;
452  pipes[i][1] = -1;
453  }
454 
455  for (i = 0; i < options->stdio_count; i++) {
456  err = uv__process_init_stdio(options->stdio + i, pipes[i]);
457  if (err)
458  goto error;
459  }
460 
461  /* This pipe is used by the parent to wait until
462  * the child has called `execve()`. We need this
463  * to avoid the following race condition:
464  *
465  * if ((pid = fork()) > 0) {
466  * kill(pid, SIGTERM);
467  * }
468  * else if (pid == 0) {
469  * execve("/bin/cat", argp, envp);
470  * }
471  *
472  * The parent sends a signal immediately after forking.
473  * Since the child may not have called `execve()` yet,
474  * there is no telling what process receives the signal,
475  * our fork or /bin/cat.
476  *
477  * To avoid ambiguity, we create a pipe with both ends
478  * marked close-on-exec. Then, after the call to `fork()`,
479  * the parent polls the read end until it EOFs or errors with EPIPE.
480  */
481  err = uv__make_pipe(signal_pipe, 0);
482  if (err)
483  goto error;
484 
485  uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD);
486 
487  /* Acquire write lock to prevent opening new fds in worker threads */
488  uv_rwlock_wrlock(&loop->cloexec_lock);
489  pid = fork();
490 
491  if (pid == -1) {
492  err = UV__ERR(errno);
493  uv_rwlock_wrunlock(&loop->cloexec_lock);
494  uv__close(signal_pipe[0]);
495  uv__close(signal_pipe[1]);
496  goto error;
497  }
498 
499  if (pid == 0) {
500  uv__process_child_init(options, stdio_count, pipes, signal_pipe[1]);
501  abort();
502  }
503 
504  /* Release lock in parent process */
505  uv_rwlock_wrunlock(&loop->cloexec_lock);
506  uv__close(signal_pipe[1]);
507 
508  process->status = 0;
509  exec_errorno = 0;
510  do
511  r = read(signal_pipe[0], &exec_errorno, sizeof(exec_errorno));
512  while (r == -1 && errno == EINTR);
513 
514  if (r == 0)
515  ; /* okay, EOF */
516  else if (r == sizeof(exec_errorno)) {
517  do
518  err = waitpid(pid, &status, 0); /* okay, read errorno */
519  while (err == -1 && errno == EINTR);
520  assert(err == pid);
521  } else if (r == -1 && errno == EPIPE) {
522  do
523  err = waitpid(pid, &status, 0); /* okay, got EPIPE */
524  while (err == -1 && errno == EINTR);
525  assert(err == pid);
526  } else
527  abort();
528 
529  uv__close_nocheckstdio(signal_pipe[0]);
530 
531  for (i = 0; i < options->stdio_count; i++) {
532  err = uv__process_open_stream(options->stdio + i, pipes[i]);
533  if (err == 0)
534  continue;
535 
536  while (i--)
538 
539  goto error;
540  }
541 
542  /* Only activate this handle if exec() happened successfully */
543  if (exec_errorno == 0) {
544  QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue);
546  }
547 
548  process->pid = pid;
549  process->exit_cb = options->exit_cb;
550 
551  if (pipes != pipes_storage)
552  uv__free(pipes);
553 
554  return exec_errorno;
555 
556 error:
557  if (pipes != NULL) {
558  for (i = 0; i < stdio_count; i++) {
559  if (i < options->stdio_count)
560  if (options->stdio[i].flags & (UV_INHERIT_FD | UV_INHERIT_STREAM))
561  continue;
562  if (pipes[i][0] != -1)
563  uv__close_nocheckstdio(pipes[i][0]);
564  if (pipes[i][1] != -1)
565  uv__close_nocheckstdio(pipes[i][1]);
566  }
567 
568  if (pipes != pipes_storage)
569  uv__free(pipes);
570  }
571 
572  return err;
573 #endif
574 }
#define ARRAY_SIZE(a)
lzma_index ** i
Definition: index.h:629
#define r
Definition: crypto_rc6.c:12
static int
Definition: sfsocketcall.h:114
int uv__close_nocheckstdio(int fd)
Definition: core.c:550
static int uv__process_open_stream(uv_stdio_container_t *container, int pipefds[2])
Definition: process.c:217
static int uv__process_init_stdio(uv_stdio_container_t *container, int fds[2])
Definition: process.c:180
static void uv__chld(uv_signal_t *handle, int signum)
Definition: process.c:48
static void uv__process_child_init(const uv_process_options_t *options, int stdio_count, int(*pipes)[2], int error_fd)
Definition: process.c:267
int uv__make_pipe(int fds[2], int flags)
Definition: process.c:142
static void uv__process_close_stream(uv_stdio_container_t *container)
Definition: process.c:242
void error(const char *msg)
Definition: untgz.c:593
void * uv__malloc(size_t size)
Definition: uv-common.c:75
void uv__free(void *ptr)
Definition: uv-common.c:81
#define uv__handle_init(loop_, h, type_)
Definition: uv-common.h:301
#define uv__handle_start(h)
Definition: uv-common.h:258
@ UV_PROCESS_WINDOWS_HIDE_CONSOLE
Definition: uv.h:1036
@ UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS
Definition: uv.h:1017
@ UV_PROCESS_WINDOWS_HIDE
Definition: uv.h:1030
@ UV_PROCESS_WINDOWS_HIDE_GUI
Definition: uv.h:1042
UV_EXTERN void uv_rwlock_wrlock(uv_rwlock_t *rwlock)
Definition: thread.c:393
UV_EXTERN int uv_signal_start(uv_signal_t *handle, uv_signal_cb signal_cb, int signum)
Definition: signal.c:340
UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t *rwlock)
Definition: thread.c:413
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115

Variable Documentation

◆ environ

char** environ
extern

Referenced by uv__process_child_init().