Rizin
unix-like reverse engineering framework and cli tools
process.c
Go to the documentation of this file.
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  *
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:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
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
19  * IN THE SOFTWARE.
20  */
21 
22 #include "uv.h"
23 #include "internal.h"
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <errno.h>
29 
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <poll.h>
35 
36 #if defined(__APPLE__) && !TARGET_OS_IPHONE
37 # include <crt_externs.h>
38 # define environ (*_NSGetEnviron())
39 #else
40 extern char **environ;
41 #endif
42 
43 #if defined(__linux__) || defined(__GLIBC__)
44 # include <grp.h>
45 #endif
46 
47 
48 static void uv__chld(uv_signal_t* handle, int signum) {
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 }
113 
114 
115 static int uv__make_socketpair(int fds[2]) {
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 }
140 
141 
142 int uv__make_pipe(int fds[2], int flags) {
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 }
174 
175 
176 /*
177  * Used for initializing stdio streams like options.stdin_stream. Returns
178  * zero on success. See also the cleanup section in uv_spawn().
179  */
180 static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) {
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 }
215 
216 
218  int pipefds[2]) {
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 }
240 
241 
243  if (!(container->flags & UV_CREATE_PIPE)) return;
244  uv__stream_close(container->data.stream);
245 }
246 
247 
248 static void uv__write_int(int fd, int val) {
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 }
260 
261 
262 #if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH))
263 /* execvp is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED, so must be
264  * avoided. Since this isn't called on those targets, the function
265  * doesn't even need to be defined for them.
266  */
268  int stdio_count,
269  int (*pipes)[2],
270  int error_fd) {
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 }
405 #endif
406 
407 
410  const uv_process_options_t* options) {
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 }
575 
576 
578  return uv_kill(process->pid, signum);
579 }
580 
581 
582 int uv_kill(int pid, int signum) {
583  if (kill(pid, signum))
584  return UV__ERR(errno);
585  else
586  return 0;
587 }
588 
589 
591  QUEUE_REMOVE(&handle->queue);
593  if (QUEUE_EMPTY(&handle->loop->process_handles))
594  uv_signal_stop(&handle->loop->child_watcher);
595 }
#define mask()
#define ARRAY_SIZE(a)
lzma_index ** i
Definition: index.h:629
ut16 val
Definition: armass64_const.h:6
static bool err
Definition: armass.c:435
static mcore_handle handle
Definition: asm_mcore.c:8
#define O_CLOEXEC
Definition: compat.h:80
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
static static fork const void static count static fd const char const char static newpath chdir
Definition: sflib.h:33
static static fork write
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
#define UV__ERR(x)
Definition: errno.h:29
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
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 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
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 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)
int n
Definition: mipsasm.c:19
#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
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
static int
Definition: sfsocketcall.h:114
#define AF_UNIX
Definition: sftypes.h:285
#define EINTR
Definition: sftypes.h:114
#define ECHILD
Definition: sftypes.h:120
#define EPIPE
Definition: sftypes.h:142
#define O_RDONLY
Definition: sftypes.h:486
@ SOCK_STREAM
Definition: sftypes.h:224
int pid_t
Definition: sftypes.h:38
#define F_DUPFD
Definition: sftypes.h:503
#define O_RDWR
Definition: sftypes.h:488
int ssize_t
Definition: sftypes.h:39
int sigset_t
Definition: sftypes.h:63
#define h(i)
Definition: sha256.c:48
Definition: uv.h:1780
uv_stream_t * stream
Definition: uv.h:946
uv_stdio_flags flags
Definition: uv.h:943
union uv_stdio_container_s::@397 data
uv_loop_t * loop
Definition: main.c:7
int uv__close_nocheckstdio(int fd)
Definition: core.c:550
int uv__nonblock_fcntl(int fd, int set)
Definition: core.c:608
int uv__cloexec_fcntl(int fd, int set)
Definition: core.c:639
int uv__close(int fd)
Definition: core.c:569
#define uv__cloexec
Definition: internal.h:169
int uv__stream_open(uv_stream_t *, int fd, int flags)
Definition: stream.c:406
#define UV__F_NONBLOCK
Definition: internal.h:288
#define uv__stream_fd(handle)
Definition: internal.h:282
#define uv__nonblock
Definition: internal.h:170
#define SAVE_ERRNO(block)
Definition: internal.h:92
void uv__stream_close(uv_stream_t *handle)
Definition: stream.c:1633
static enum exit_status_type exit_status
Exit status to use. This can be changed with set_exit_status().
Definition: main.c:17
#define fail(test)
Definition: tests.h:29
int uv_spawn(uv_loop_t *loop, uv_process_t *process, const uv_process_options_t *options)
Definition: process.c:408
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
int uv_kill(int pid, int signum)
Definition: process.c:582
int uv_process_kill(uv_process_t *process, int signum)
Definition: process.c:577
static void uv__write_int(int fd, int val)
Definition: process.c:248
static void uv__chld(uv_signal_t *handle, int signum)
Definition: process.c:48
static int uv__make_socketpair(int fds[2])
Definition: process.c:115
char ** environ
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
void uv__process_close(uv_process_t *handle)
Definition: process.c:590
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
@ UV_HANDLE_WRITABLE
Definition: uv-common.h:93
@ UV_HANDLE_READABLE
Definition: uv-common.h:92
#define uv__handle_init(loop_, h, type_)
Definition: uv-common.h:301
#define uv__handle_stop(h)
Definition: uv-common.h:266
#define uv__handle_start(h)
Definition: uv-common.h:258
@ UV_INHERIT_FD
Definition: uv.h:924
@ UV_CREATE_PIPE
Definition: uv.h:923
@ UV_WRITABLE_PIPE
Definition: uv.h:933
@ UV_IGNORE
Definition: uv.h:922
@ UV_INHERIT_STREAM
Definition: uv.h:925
@ UV_READABLE_PIPE
Definition: uv.h:932
@ 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_SETUID
Definition: uv.h:1005
@ UV_PROCESS_SETGID
Definition: uv.h:1011
@ UV_PROCESS_DETACHED
Definition: uv.h:1025
@ 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
UV_EXTERN int uv_signal_stop(uv_signal_t *handle)
Definition: signal.c:513
#define SIGKILL
Definition: process.c:37
uv_pipe_t queue
Definition: worker.c:9
static const z80_opcode fd[]
Definition: z80_tab.h:997
static zip_compression_status_t process(void *ud, zip_uint8_t *data, zip_uint64_t *length)
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115