Tor  0.4.4.0-alpha-dev
process_unix.c
Go to the documentation of this file.
1 /* Copyright (c) 2003, Roger Dingledine
2  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3  * Copyright (c) 2007-2020, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
6 /**
7  * \file process_unix.c
8  * \brief Module for working with Unix processes.
9  **/
10 
11 #define PROCESS_UNIX_PRIVATE
12 #include "lib/intmath/cmp.h"
13 #include "lib/buf/buffers.h"
14 #include "lib/net/buffers_net.h"
17 #include "lib/log/log.h"
18 #include "lib/log/util_bug.h"
19 #include "lib/process/process.h"
21 #include "lib/process/waitpid.h"
22 #include "lib/process/env.h"
23 
24 #include <stdio.h>
25 
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #endif
29 
30 #ifdef HAVE_ERRNO_H
31 #include <errno.h>
32 #endif
33 
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37 
38 #ifdef HAVE_FCNTL_H
39 #include <fcntl.h>
40 #endif
41 
42 #if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
43 #include <sys/prctl.h>
44 #endif
45 
46 #if HAVE_SIGNAL_H
47 #include <signal.h>
48 #endif
49 
50 #ifndef _WIN32
51 
52 /** Maximum number of file descriptors, if we cannot get it via sysconf() */
53 #define DEFAULT_MAX_FD 256
54 
55 /** Internal state for Unix handles. */
57  /** Unix File Descriptor. */
58  int fd;
59 
60  /** Have we reached end of file? */
62 
63  /** Event structure for libevent. */
64  struct event *event;
65 
66  /** Are we writing? */
67  bool is_writing;
68 };
69 
70 /** Internal state for our Unix process. */
72  /** Standard in handle. */
74 
75  /** Standard out handle. */
77 
78  /** Standard error handle. */
80 
81  /** The process identifier of our process. */
82  pid_t pid;
83 
84  /** Waitpid Callback structure. */
86 };
87 
88 /** Returns a newly allocated <b>process_unix_t</b>. */
91 {
92  process_unix_t *unix_process;
93  unix_process = tor_malloc_zero(sizeof(process_unix_t));
94 
95  unix_process->stdin_handle.fd = -1;
96  unix_process->stderr_handle.fd = -1;
97  unix_process->stdout_handle.fd = -1;
98 
99  return unix_process;
100 }
101 
102 /** Deallocates the given <b>unix_process</b>. */
103 void
105 {
106  if (! unix_process)
107  return;
108 
109  /* Clean up our waitpid callback. */
110  clear_waitpid_callback(unix_process->waitpid);
111 
112  /* FIXME(ahf): Refactor waitpid code? */
113  unix_process->waitpid = NULL;
114 
115  /* Close all our file descriptors. */
117 
118  tor_event_free(unix_process->stdout_handle.event);
119  tor_event_free(unix_process->stderr_handle.event);
120  tor_event_free(unix_process->stdin_handle.event);
121 
122  tor_free(unix_process);
123 }
124 
125 /** Executes the given process as a child process of Tor. This function is
126  * responsible for setting up the child process and run it. This includes
127  * setting up pipes for interprocess communication, initialize the waitpid
128  * callbacks, and finally run fork() followed by execve(). Returns
129  * <b>PROCESS_STATUS_RUNNING</b> upon success. */
132 {
133  static int max_fd = -1;
134 
135  process_unix_t *unix_process;
136  pid_t pid;
137  int stdin_pipe[2];
138  int stdout_pipe[2];
139  int stderr_pipe[2];
140  int retval, fd;
141 
142  unix_process = process_get_unix_process(process);
143 
144  /* Create standard in pipe. */
145  retval = pipe(stdin_pipe);
146 
147  if (-1 == retval) {
148  log_warn(LD_PROCESS,
149  "Unable to create pipe for stdin "
150  "communication with process: %s",
151  strerror(errno));
152 
153  return PROCESS_STATUS_ERROR;
154  }
155 
156  /* Create standard out pipe. */
157  retval = pipe(stdout_pipe);
158 
159  if (-1 == retval) {
160  log_warn(LD_PROCESS,
161  "Unable to create pipe for stdout "
162  "communication with process: %s",
163  strerror(errno));
164 
165  /** Cleanup standard in pipe. */
166  close(stdin_pipe[0]);
167  close(stdin_pipe[1]);
168 
169  return PROCESS_STATUS_ERROR;
170  }
171 
172  /* Create standard error pipe. */
173  retval = pipe(stderr_pipe);
174 
175  if (-1 == retval) {
176  log_warn(LD_PROCESS,
177  "Unable to create pipe for stderr "
178  "communication with process: %s",
179  strerror(errno));
180 
181  /** Cleanup standard in pipe. */
182  close(stdin_pipe[0]);
183  close(stdin_pipe[1]);
184 
185  /** Cleanup standard out pipe. */
186  close(stdout_pipe[0]);
187  close(stdout_pipe[1]);
188 
189  return PROCESS_STATUS_ERROR;
190  }
191 
192 #ifdef _SC_OPEN_MAX
193  if (-1 == max_fd) {
194  max_fd = (int)sysconf(_SC_OPEN_MAX);
195 
196  if (max_fd == -1) {
197  max_fd = DEFAULT_MAX_FD;
198  log_warn(LD_PROCESS,
199  "Cannot find maximum file descriptor, assuming: %d", max_fd);
200  }
201  }
202 #else /* !defined(_SC_OPEN_MAX) */
203  max_fd = DEFAULT_MAX_FD;
204 #endif /* defined(_SC_OPEN_MAX) */
205 
206  pid = fork();
207 
208  if (0 == pid) {
209  /* This code is running in the child process context. */
210 
211 #if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
212  /* Attempt to have the kernel issue a SIGTERM if the parent
213  * goes away. Certain attributes of the binary being execve()ed
214  * will clear this during the execve() call, but it's better
215  * than nothing.
216  */
217  prctl(PR_SET_PDEATHSIG, SIGTERM);
218 #endif /* defined(HAVE_SYS_PRCTL_H) && defined(__linux__) */
219 
220  /* Link process stdout to the write end of the pipe. */
221  retval = dup2(stdout_pipe[1], STDOUT_FILENO);
222  if (-1 == retval)
223  goto error;
224 
225  /* Link process stderr to the write end of the pipe. */
226  retval = dup2(stderr_pipe[1], STDERR_FILENO);
227  if (-1 == retval)
228  goto error;
229 
230  /* Link process stdin to the read end of the pipe */
231  retval = dup2(stdin_pipe[0], STDIN_FILENO);
232  if (-1 == retval)
233  goto error;
234 
235  /* Close our pipes now after they have been dup2()'ed. */
236  close(stderr_pipe[0]);
237  close(stderr_pipe[1]);
238  close(stdout_pipe[0]);
239  close(stdout_pipe[1]);
240  close(stdin_pipe[0]);
241  close(stdin_pipe[1]);
242 
243  /* Close all other fds, including the read end of the pipe. XXX: We should
244  * now be doing enough FD_CLOEXEC setting to make this needless.
245  */
246  for (fd = STDERR_FILENO + 1; fd < max_fd; fd++)
247  close(fd);
248 
249  /* Create the argv value for our new process. */
250  char **argv = process_get_argv(process);
251 
252  /* Create the env value for our new process. */
254 
255  /* Call the requested program. */
256  execve(argv[0], argv, env->unixoid_environment_block);
257 
258  /* If we made it here it is because execve failed :-( */
259  tor_free(argv);
260  process_environment_free(env);
261 
262  error:
263  fprintf(stderr, "Error from child process: %s", strerror(errno));
264  _exit(1);
265  }
266 
267  /* We are in the parent process. */
268  if (-1 == pid) {
269  log_warn(LD_PROCESS,
270  "Failed to create child process: %s", strerror(errno));
271 
272  /** Cleanup standard in pipe. */
273  close(stdin_pipe[0]);
274  close(stdin_pipe[1]);
275 
276  /** Cleanup standard out pipe. */
277  close(stdout_pipe[0]);
278  close(stdout_pipe[1]);
279 
280  /** Cleanup standard error pipe. */
281  close(stderr_pipe[0]);
282  close(stderr_pipe[1]);
283 
284  return PROCESS_STATUS_ERROR;
285  }
286 
287  /* Register our PID. */
288  unix_process->pid = pid;
289 
290  /* Setup waitpid callbacks. */
291  unix_process->waitpid = set_waitpid_callback(pid,
293  process);
294 
295  /* Handle standard out. */
296  unix_process->stdout_handle.fd = stdout_pipe[0];
297  retval = close(stdout_pipe[1]);
298 
299  if (-1 == retval) {
300  log_warn(LD_PROCESS, "Failed to close write end of standard out pipe: %s",
301  strerror(errno));
302  }
303 
304  /* Handle standard error. */
305  unix_process->stderr_handle.fd = stderr_pipe[0];
306  retval = close(stderr_pipe[1]);
307 
308  if (-1 == retval) {
309  log_warn(LD_PROCESS,
310  "Failed to close write end of standard error pipe: %s",
311  strerror(errno));
312  }
313 
314  /* Handle standard in. */
315  unix_process->stdin_handle.fd = stdin_pipe[1];
316  retval = close(stdin_pipe[0]);
317 
318  if (-1 == retval) {
319  log_warn(LD_PROCESS, "Failed to close read end of standard in pipe: %s",
320  strerror(errno));
321  }
322 
323  /* Setup our handles. */
325  &unix_process->stdout_handle,
326  EV_READ|EV_PERSIST,
328 
330  &unix_process->stderr_handle,
331  EV_READ|EV_PERSIST,
333 
335  &unix_process->stdin_handle,
336  EV_WRITE|EV_PERSIST,
338 
339  /* Start reading from standard out and standard error. */
342 
343  return PROCESS_STATUS_RUNNING;
344 }
345 
346 /** Terminate the given process. Returns true on success, otherwise false. */
347 bool
349 {
350  tor_assert(process);
351 
352  process_unix_t *unix_process = process_get_unix_process(process);
353 
354  /* All running processes should have a waitpid. */
355  if (BUG(unix_process->waitpid == NULL))
356  return false;
357 
358  bool success = true;
359 
360  /* Send a SIGTERM to our child process. */
361  int ret;
362 
363  ret = kill(unix_process->pid, SIGTERM);
364 
365  if (ret == -1) {
366  log_warn(LD_PROCESS, "Unable to terminate process: %s",
367  strerror(errno));
368  success = false;
369  }
370 
371  /* Close all our FD's. */
372  if (! process_unix_close_file_descriptors(unix_process))
373  success = false;
374 
375  return success;
376 }
377 
378 /** Returns the unique process identifier for the given <b>process</b>. */
379 process_pid_t
381 {
382  tor_assert(process);
383 
384  process_unix_t *unix_process = process_get_unix_process(process);
385  return (process_pid_t)unix_process->pid;
386 }
387 
388 /** Write the given <b>buffer</b> as input to the given <b>process</b>'s
389  * standard input. Returns the number of bytes written. */
390 int
391 process_unix_write(process_t *process, buf_t *buffer)
392 {
393  tor_assert(process);
394  tor_assert(buffer);
395 
396  process_unix_t *unix_process = process_get_unix_process(process);
397 
398  size_t buffer_flush_len = buf_datalen(buffer);
399  const size_t max_to_write = MIN(PROCESS_MAX_WRITE, buffer_flush_len);
400 
401  /* If we have data to write (when buffer_flush_len > 0) and we are not
402  * currently getting file descriptor events from the kernel, we tell the
403  * kernel to start notifying us about when we can write to our file
404  * descriptor and return. */
405  if (buffer_flush_len > 0 && ! unix_process->stdin_handle.is_writing) {
407  return 0;
408  }
409 
410  /* We don't have any data to write, but the kernel is currently notifying us
411  * about whether we are able to write or not. Tell the kernel to stop
412  * notifying us until we have data to write. */
413  if (buffer_flush_len == 0 && unix_process->stdin_handle.is_writing) {
414  process_unix_stop_writing(&unix_process->stdin_handle);
415  return 0;
416  }
417 
418  /* We have data to write and the kernel have told us to write it. */
419  return buf_flush_to_pipe(buffer,
420  process_get_unix_process(process)->stdin_handle.fd,
421  max_to_write, &buffer_flush_len);
422 }
423 
424 /** Read data from the given process's standard output and put it into
425  * <b>buffer</b>. Returns the number of bytes read. */
426 int
427 process_unix_read_stdout(process_t *process, buf_t *buffer)
428 {
429  tor_assert(process);
430  tor_assert(buffer);
431 
432  process_unix_t *unix_process = process_get_unix_process(process);
433 
434  return process_unix_read_handle(process,
435  &unix_process->stdout_handle,
436  buffer);
437 }
438 
439 /** Read data from the given process's standard error and put it into
440  * <b>buffer</b>. Returns the number of bytes read. */
441 int
442 process_unix_read_stderr(process_t *process, buf_t *buffer)
443 {
444  tor_assert(process);
445  tor_assert(buffer);
446 
447  process_unix_t *unix_process = process_get_unix_process(process);
448 
449  return process_unix_read_handle(process,
450  &unix_process->stderr_handle,
451  buffer);
452 }
453 
454 /** This function is called whenever libevent thinks we have data that could be
455  * read from the child process's standard output. We notify the Process
456  * subsystem, which is then responsible for calling back to us for doing the
457  * actual reading of the data. */
458 STATIC void
459 stdout_read_callback(evutil_socket_t fd, short event, void *data)
460 {
461  (void)fd;
462  (void)event;
463 
464  process_t *process = data;
465  tor_assert(process);
466 
468 }
469 
470 /** This function is called whenever libevent thinks we have data that could be
471  * read from the child process's standard error. We notify the Process
472  * subsystem, which is then responsible for calling back to us for doing the
473  * actual reading of the data. */
474 STATIC void
475 stderr_read_callback(evutil_socket_t fd, short event, void *data)
476 {
477  (void)fd;
478  (void)event;
479 
480  process_t *process = data;
481  tor_assert(process);
482 
484 }
485 
486 /** This function is called whenever libevent thinks we have data that could be
487  * written the child process's standard input. We notify the Process subsystem,
488  * which is then responsible for calling back to us for doing the actual write
489  * of the data. */
490 STATIC void
491 stdin_write_callback(evutil_socket_t fd, short event, void *data)
492 {
493  (void)fd;
494  (void)event;
495 
496  process_t *process = data;
497  tor_assert(process);
498 
500 }
501 
502 /** This function tells libevent that we are interested in receiving read
503  * events from the given <b>handle</b>. */
504 STATIC void
506 {
507  tor_assert(handle);
508 
509  if (event_add(handle->event, NULL))
510  log_warn(LD_PROCESS,
511  "Unable to add libevent event for handle.");
512 }
513 
514 /** This function tells libevent that we are no longer interested in receiving
515  * read events from the given <b>handle</b>. */
516 STATIC void
518 {
519  tor_assert(handle);
520 
521  if (handle->event == NULL)
522  return;
523 
524  if (event_del(handle->event))
525  log_warn(LD_PROCESS,
526  "Unable to delete libevent event for handle.");
527 }
528 
529 /** This function tells libevent that we are interested in receiving write
530  * events from the given <b>handle</b>. */
531 STATIC void
533 {
534  tor_assert(handle);
535 
536  if (event_add(handle->event, NULL))
537  log_warn(LD_PROCESS,
538  "Unable to add libevent event for handle.");
539 
540  handle->is_writing = true;
541 }
542 
543 /** This function tells libevent that we are no longer interested in receiving
544  * write events from the given <b>handle</b>. */
545 STATIC void
547 {
548  tor_assert(handle);
549 
550  if (handle->event == NULL)
551  return;
552 
553  if (event_del(handle->event))
554  log_warn(LD_PROCESS,
555  "Unable to delete libevent event for handle.");
556 
557  handle->is_writing = false;
558 }
559 
560 /** This function is called when the waitpid system have detected that our
561  * process have terminated. We disable the waitpid system and notify the
562  * Process subsystem that we have terminated. */
563 STATIC void
564 process_unix_waitpid_callback(int status, void *data)
565 {
566  tor_assert(data);
567 
568  process_t *process = data;
569  process_unix_t *unix_process = process_get_unix_process(process);
570 
571  /* Remove our waitpid callback. */
572  clear_waitpid_callback(unix_process->waitpid);
573  unix_process->waitpid = NULL;
574 
575  /* Notify our process. */
576  process_notify_event_exit(process, status);
577 
578  /* Make sure you don't modify the process after we have called
579  * process_notify_event_exit() on it, to allow users to process_free() it in
580  * the exit callback. */
581 }
582 
583 /** This function sets the file descriptor in the <b>handle</b> as non-blocking
584  * and configures the libevent event structure based on the given <b>flags</b>
585  * to ensure that <b>callback</b> is called whenever we have events on the
586  * given <b>handle</b>. */
587 STATIC void
589  process_unix_handle_t *handle,
590  short flags,
591  event_callback_fn callback)
592 {
593  tor_assert(process);
594  tor_assert(handle);
595  tor_assert(callback);
596 
597  /* Put our file descriptor into non-blocking mode. */
598  if (fcntl(handle->fd, F_SETFL, O_NONBLOCK) < 0) {
599  log_warn(LD_PROCESS, "Unable mark Unix handle as non-blocking: %s",
600  strerror(errno));
601  }
602 
603  /* Setup libevent event. */
604  handle->event = tor_event_new(tor_libevent_get_base(),
605  handle->fd,
606  flags,
607  callback,
608  process);
609 }
610 
611 /** This function reads data from the given <b>handle</b> and puts it into
612  * <b>buffer</b>. Returns the number of bytes read this way. */
613 STATIC int
615  process_unix_handle_t *handle,
616  buf_t *buffer)
617 {
618  tor_assert(process);
619  tor_assert(handle);
620  tor_assert(buffer);
621 
622  int ret = 0;
623  int eof = 0;
624  int error = 0;
625 
626  ret = buf_read_from_pipe(buffer,
627  handle->fd,
629  &eof,
630  &error);
631 
632  if (error)
633  log_warn(LD_PROCESS,
634  "Unable to read data: %s", strerror(error));
635 
636  if (eof) {
637  handle->reached_eof = true;
639  }
640 
641  return ret;
642 }
643 
644 /** Close the standard in, out, and error handles of the given
645  * <b>unix_process</b>. */
646 STATIC bool
648 {
649  tor_assert(unix_process);
650 
651  int ret;
652  bool success = true;
653 
654  /* Stop reading and writing before we close() our
655  * file descriptors. */
656  if (! unix_process->stdout_handle.reached_eof)
658 
659  if (! unix_process->stderr_handle.reached_eof)
661 
662  if (unix_process->stdin_handle.is_writing)
663  process_unix_stop_writing(&unix_process->stdin_handle);
664 
665  if (unix_process->stdin_handle.fd != -1) {
666  ret = close(unix_process->stdin_handle.fd);
667  if (ret == -1) {
668  log_warn(LD_PROCESS, "Unable to close standard in");
669  success = false;
670  }
671 
672  unix_process->stdin_handle.fd = -1;
673  }
674 
675  if (unix_process->stdout_handle.fd != -1) {
676  ret = close(unix_process->stdout_handle.fd);
677  if (ret == -1) {
678  log_warn(LD_PROCESS, "Unable to close standard out");
679  success = false;
680  }
681 
682  unix_process->stdout_handle.fd = -1;
683  }
684 
685  if (unix_process->stderr_handle.fd != -1) {
686  ret = close(unix_process->stderr_handle.fd);
687  if (ret == -1) {
688  log_warn(LD_PROCESS, "Unable to close standard error");
689  success = false;
690  }
691 
692  unix_process->stderr_handle.fd = -1;
693  }
694 
695  return success;
696 }
697 
698 #endif /* !defined(_WIN32) */
tor_free
#define tor_free(p)
Definition: malloc.h:52
waitpid_callback_t
Definition: waitpid.c:35
stderr_read_callback
STATIC void stderr_read_callback(evutil_socket_t fd, short event, void *data)
Definition: process_unix.c:475
process_unix_read_handle
STATIC int process_unix_read_handle(process_t *process, process_unix_handle_t *handle, buf_t *buffer)
Definition: process_unix.c:614
process_unix_t::stdout_handle
process_unix_handle_t stdout_handle
Definition: process_unix.c:76
smartlist.h
Header for smartlist.c.
cmp.h
Macro definitions for MIN, MAX, and CLAMP.
tor_assert
#define tor_assert(expr)
Definition: util_bug.h:102
process_unix_handle_t::fd
int fd
Definition: process_unix.c:58
process_unix_t::waitpid
waitpid_callback_t * waitpid
Definition: process_unix.c:85
process_environment_t::unixoid_environment_block
char ** unixoid_environment_block
Definition: env.h:27
process_notify_event_stderr
void process_notify_event_stderr(process_t *process)
Definition: process.c:594
clear_waitpid_callback
void clear_waitpid_callback(waitpid_callback_t *ent)
Definition: waitpid.c:98
env.h
Header for env.c.
buf_read_from_pipe
int buf_read_from_pipe(buf_t *buf, int fd, size_t at_most, int *reached_eof, int *socket_error)
Definition: buffers_net.c:269
util_bug.h
Macros to manage assertions, fatal and non-fatal.
process_unix_start_writing
STATIC void process_unix_start_writing(process_unix_handle_t *handle)
Definition: process_unix.c:532
buf_datalen
size_t buf_datalen(const buf_t *buf)
Definition: buffers.c:394
LD_PROCESS
#define LD_PROCESS
Definition: log.h:115
process_unix_t
Definition: process_unix.c:71
process_get_argv
char ** process_get_argv(const process_t *process)
Definition: process.c:439
process.h
Header for process.c.
process_t
Definition: process.c:36
process_unix.h
Header for process_unix.c.
DEFAULT_MAX_FD
#define DEFAULT_MAX_FD
Definition: process_unix.c:53
process_status_t
process_status_t
Definition: process.h:26
process_unix_free_
void process_unix_free_(process_unix_t *unix_process)
Definition: process_unix.c:104
stdout_read_callback
STATIC void stdout_read_callback(evutil_socket_t fd, short event, void *data)
Definition: process_unix.c:459
process_unix_t::stderr_handle
process_unix_handle_t stderr_handle
Definition: process_unix.c:79
process_unix_handle_t::event
struct event * event
Definition: process_unix.c:64
process_notify_event_stdin
void process_notify_event_stdin(process_t *process)
Definition: process.c:610
buffers.h
Header file for buffers.c.
process_unix_handle_t
Definition: process_unix.c:56
process_unix_exec
process_status_t process_unix_exec(process_t *process)
Definition: process_unix.c:131
waitpid.h
Headers for waitpid.c.
process_unix_terminate
bool process_unix_terminate(process_t *process)
Definition: process_unix.c:348
tor_libevent_get_base
struct event_base * tor_libevent_get_base(void)
Definition: compat_libevent.c:196
log.h
Headers for log.c.
process_notify_event_stdout
void process_notify_event_stdout(process_t *process)
Definition: process.c:577
process_get_environment
process_environment_t * process_get_environment(const process_t *process)
Definition: process.c:501
process_unix_read_stderr
int process_unix_read_stderr(process_t *process, buf_t *buffer)
Definition: process_unix.c:442
process_get_unix_process
process_unix_t * process_get_unix_process(const process_t *process)
Definition: process.c:510
process_unix_waitpid_callback
STATIC void process_unix_waitpid_callback(int status, void *data)
Definition: process_unix.c:564
process_unix_close_file_descriptors
STATIC bool process_unix_close_file_descriptors(process_unix_t *unix_process)
Definition: process_unix.c:647
stdin_write_callback
STATIC void stdin_write_callback(evutil_socket_t fd, short event, void *data)
Definition: process_unix.c:491
PROCESS_STATUS_ERROR
@ PROCESS_STATUS_ERROR
Definition: process.h:34
process_unix_get_pid
process_pid_t process_unix_get_pid(process_t *process)
Definition: process_unix.c:380
process_unix_handle_t::is_writing
bool is_writing
Definition: process_unix.c:67
process_unix_read_stdout
int process_unix_read_stdout(process_t *process, buf_t *buffer)
Definition: process_unix.c:427
process_unix_t::stdin_handle
process_unix_handle_t stdin_handle
Definition: process_unix.c:73
PROCESS_MAX_WRITE
#define PROCESS_MAX_WRITE
Definition: process.h:21
process_environment_t
Definition: env.h:21
PROCESS_STATUS_RUNNING
@ PROCESS_STATUS_RUNNING
Definition: process.h:31
buf_flush_to_pipe
int buf_flush_to_pipe(buf_t *buf, int fd, size_t sz, size_t *buf_flushlen)
Definition: buffers_net.c:257
buffers_net.h
Header file for buffers_net.c.
process_unix_setup_handle
STATIC void process_unix_setup_handle(process_t *process, process_unix_handle_t *handle, short flags, event_callback_fn callback)
Definition: process_unix.c:588
process_unix_stop_reading
STATIC void process_unix_stop_reading(process_unix_handle_t *handle)
Definition: process_unix.c:517
STATIC
#define STATIC
Definition: testsupport.h:32
process_unix_write
int process_unix_write(process_t *process, buf_t *buffer)
Definition: process_unix.c:391
PROCESS_MAX_READ
#define PROCESS_MAX_READ
Definition: process.h:24
process_unix_t::pid
pid_t pid
Definition: process_unix.c:82
process_notify_event_exit
void process_notify_event_exit(process_t *process, process_exit_code_t exit_code)
Definition: process.c:623
compat_libevent.h
Header for compat_libevent.c.
process_unix_stop_writing
STATIC void process_unix_stop_writing(process_unix_handle_t *handle)
Definition: process_unix.c:546
process_unix_handle_t::reached_eof
bool reached_eof
Definition: process_unix.c:61
process_unix_new
process_unix_t * process_unix_new(void)
Definition: process_unix.c:90
process_unix_start_reading
STATIC void process_unix_start_reading(process_unix_handle_t *handle)
Definition: process_unix.c:505