unix/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 
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);
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  */
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)
328  uv__nonblock_fcntl(fd, 0);
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  */
354  SAVE_ERRNO(setgroups(0, NULL));
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 }
UV_HANDLE_WRITABLE
@ UV_HANDLE_WRITABLE
Definition: uv-common.h:85
uv__process_open_stream
static int uv__process_open_stream(uv_stdio_container_t *container, int pipefds[2])
Definition: unix/process.c:217
async_greeter_server_with_graceful_shutdown.loop
loop
Definition: async_greeter_server_with_graceful_shutdown.py:59
uv_process_options_s
Definition: uv.h:940
uv__stream_close
void uv__stream_close(uv_stream_t *handle)
Definition: unix/stream.c:1633
uv_kill
int uv_kill(int pid, int signum)
Definition: unix/process.c:582
uv_process_s
Definition: uv.h:1037
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)
Definition: unix/process.c:267
ARRAY_SIZE
#define ARRAY_SIZE(array)
Definition: bloaty.cc:101
environ
char ** environ
Definition: bloaty/third_party/googletest/googlemock/test/gmock_leak_test.py:41
UV_READABLE_PIPE
@ UV_READABLE_PIPE
Definition: uv.h:921
UV_PROCESS_SETUID
@ UV_PROCESS_SETUID
Definition: uv.h:994
write
#define write
Definition: test-fs.c:47
UV_IGNORE
@ UV_IGNORE
Definition: uv.h:911
uv__malloc
void * uv__malloc(size_t size)
Definition: uv-common.c:75
uv__close_nocheckstdio
int uv__close_nocheckstdio(int fd)
Definition: unix/core.c:538
options
double_dict options[]
Definition: capstone_test.c:55
uv__chld
static void uv__chld(uv_signal_t *handle, int signum)
Definition: unix/process.c:48
error
grpc_error_handle error
Definition: retry_filter.cc:499
error_ref_leak.err
err
Definition: error_ref_leak.py:35
QUEUE_HEAD
#define QUEUE_HEAD(q)
Definition: queue.h:42
uv_process_kill
int uv_process_kill(uv_process_t *process, int signum)
Definition: unix/process.c:577
status
absl::Status status
Definition: rls.cc:251
uv__cloexec_fcntl
int uv__cloexec_fcntl(int fd, int set)
Definition: unix/core.c:627
QUEUE_DATA
#define QUEUE_DATA(ptr, type, field)
Definition: queue.h:30
uv__process_close_stream
static void uv__process_close_stream(uv_stdio_container_t *container)
Definition: unix/process.c:242
grpc_core::pending
P< T > pending()
Definition: try_join_test.cc:50
uv__process_close
void uv__process_close(uv_process_t *handle)
Definition: unix/process.c:590
UV__F_NONBLOCK
#define UV__F_NONBLOCK
Definition: third_party/libuv/src/unix/internal.h:291
UV_WRITABLE_PIPE
@ UV_WRITABLE_PIPE
Definition: uv.h:922
QUEUE_INIT
#define QUEUE_INIT(q)
Definition: queue.h:45
ssize_t
intptr_t ssize_t
Definition: win.h:27
process
static uv_process_t process
Definition: benchmark-spawn.c:32
xds_interop_client.int
int
Definition: xds_interop_client.py:113
queue
Definition: sync_test.cc:39
SIGKILL
#define SIGKILL
Definition: win.h:87
signal
static void signal(notification *n)
Definition: alts_tsi_handshaker_test.cc:107
uv__cloexec
#define uv__cloexec
Definition: third_party/libuv/src/unix/internal.h:173
grpc_core::fail
Poll< absl::StatusOr< std::tuple< T... > > > fail()
Definition: try_join_test.cc:45
UV_INHERIT_FD
@ UV_INHERIT_FD
Definition: uv.h:913
UV_INHERIT_STREAM
@ UV_INHERIT_STREAM
Definition: uv.h:914
uv__write_int
static void uv__write_int(int fd, int val)
Definition: unix/process.c:248
uv_rwlock_wrlock
UV_EXTERN void uv_rwlock_wrlock(uv_rwlock_t *rwlock)
Definition: libuv/src/unix/thread.c:392
uv_rwlock_wrunlock
UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t *rwlock)
Definition: libuv/src/unix/thread.c:412
uv__free
void uv__free(void *ptr)
Definition: uv-common.c:81
uv_process_s::pid
int pid
Definition: uv.h:1040
uv_spawn
int uv_spawn(uv_loop_t *loop, uv_process_t *process, const uv_process_options_t *options)
Definition: unix/process.c:408
UV__ERR
#define UV__ERR(x)
Definition: errno.h:29
uv_stdio_container_s
Definition: uv.h:931
uv_signal_stop
UV_EXTERN int uv_signal_stop(uv_signal_t *handle)
Definition: unix/signal.c:511
QUEUE_REMOVE
#define QUEUE_REMOVE(q)
Definition: queue.h:101
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
uv__handle_init
#define uv__handle_init(loop_, h, type_)
Definition: uv-common.h:284
QUEUE_EMPTY
#define QUEUE_EMPTY(q)
Definition: queue.h:39
uv__nonblock_fcntl
int uv__nonblock_fcntl(int fd, int set)
Definition: unix/core.c:596
uv.h
uv__nonblock
#define uv__nonblock
Definition: third_party/libuv/src/unix/internal.h:174
UV_PROCESS_WINDOWS_HIDE
@ UV_PROCESS_WINDOWS_HIDE
Definition: uv.h:1019
uv_signal_s
Definition: uv.h:1561
internal.h
read
int read(izstream &zs, T *x, Items items)
Definition: bloaty/third_party/zlib/contrib/iostream2/zstream.h:115
UV_HANDLE_READABLE
@ UV_HANDLE_READABLE
Definition: uv-common.h:84
UV_PROCESS_SETGID
@ UV_PROCESS_SETGID
Definition: uv.h:1000
absl::flags_internal
Definition: abseil-cpp/absl/flags/commandlineflag.h:40
QUEUE_NEXT
#define QUEUE_NEXT(q)
Definition: queue.h:24
poll.h
UV_PROCESS_WINDOWS_HIDE_GUI
@ UV_PROCESS_WINDOWS_HIDE_GUI
Definition: uv.h:1031
uv__stream_fd
#define uv__stream_fd(handle)
Definition: third_party/libuv/src/unix/internal.h:285
fix_build_deps.r
r
Definition: fix_build_deps.py:491
SAVE_ERRNO
#define SAVE_ERRNO(block)
Definition: third_party/libuv/src/unix/internal.h:94
cpp.gmock_class.set
set
Definition: bloaty/third_party/googletest/googlemock/scripts/generator/cpp/gmock_class.py:44
UV_PROCESS_DETACHED
@ UV_PROCESS_DETACHED
Definition: uv.h:1014
uv__make_socketpair
static int uv__make_socketpair(int fds[2])
Definition: unix/process.c:115
UV_CREATE_PIPE
@ UV_CREATE_PIPE
Definition: uv.h:912
open
#define open
Definition: test-fs.c:46
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS
@ UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS
Definition: uv.h:1006
handle
static csh handle
Definition: test_arm_regression.c:16
uv_handle_s
Definition: uv.h:441
uv_loop_s
Definition: uv.h:1767
flags
uint32_t flags
Definition: retry_filter.cc:632
uv__handle_start
#define uv__handle_start(h)
Definition: uv-common.h:241
uv__stream_open
int uv__stream_open(uv_stream_t *, int fd, int flags)
Definition: unix/stream.c:406
UV_PROCESS_WINDOWS_HIDE_CONSOLE
@ UV_PROCESS_WINDOWS_HIDE_CONSOLE
Definition: uv.h:1025
uv__make_pipe
int uv__make_pipe(int fds[2], int flags)
Definition: unix/process.c:142
uv_process_s::exit_cb
UV_HANDLE_FIELDS uv_exit_cb exit_cb
Definition: uv.h:1039
uv__handle_stop
#define uv__handle_stop(h)
Definition: uv-common.h:249
QUEUE_INSERT_TAIL
#define QUEUE_INSERT_TAIL(h, q)
Definition: queue.h:92
uv__process_init_stdio
static int uv__process_init_stdio(uv_stdio_container_t *container, int fds[2])
Definition: unix/process.c:180
errno.h
container
static struct async_container * container
Definition: benchmark-million-async.c:33
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
QUEUE
void * QUEUE[2]
Definition: queue.h:21
uv_signal_start
UV_EXTERN int uv_signal_start(uv_signal_t *handle, uv_signal_cb signal_cb, int signum)
Definition: unix/signal.c:338
uv__close
int uv__close(int fd)
Definition: unix/core.c:557


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:55