11 #define PROCESS_UNIX_PRIVATE
42 #if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
43 #include <sys/prctl.h>
53 #define DEFAULT_MAX_FD 256
133 static int max_fd = -1;
145 retval = pipe(stdin_pipe);
149 "Unable to create pipe for stdin "
150 "communication with process: %s",
157 retval = pipe(stdout_pipe);
161 "Unable to create pipe for stdout "
162 "communication with process: %s",
166 close(stdin_pipe[0]);
167 close(stdin_pipe[1]);
173 retval = pipe(stderr_pipe);
177 "Unable to create pipe for stderr "
178 "communication with process: %s",
182 close(stdin_pipe[0]);
183 close(stdin_pipe[1]);
186 close(stdout_pipe[0]);
187 close(stdout_pipe[1]);
194 max_fd = (int)sysconf(_SC_OPEN_MAX);
199 "Cannot find maximum file descriptor, assuming: %d", max_fd);
211 #if defined(HAVE_SYS_PRCTL_H) && defined(__linux__)
217 prctl(PR_SET_PDEATHSIG, SIGTERM);
221 retval = dup2(stdout_pipe[1], STDOUT_FILENO);
226 retval = dup2(stderr_pipe[1], STDERR_FILENO);
231 retval = dup2(stdin_pipe[0], STDIN_FILENO);
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]);
246 for (fd = STDERR_FILENO + 1; fd < max_fd; fd++)
260 process_environment_free(env);
263 fprintf(stderr,
"Error from child process: %s", strerror(errno));
270 "Failed to create child process: %s", strerror(errno));
273 close(stdin_pipe[0]);
274 close(stdin_pipe[1]);
277 close(stdout_pipe[0]);
278 close(stdout_pipe[1]);
281 close(stderr_pipe[0]);
282 close(stderr_pipe[1]);
288 unix_process->
pid = pid;
291 unix_process->
waitpid = set_waitpid_callback(pid,
297 retval = close(stdout_pipe[1]);
300 log_warn(
LD_PROCESS,
"Failed to close write end of standard out pipe: %s",
306 retval = close(stderr_pipe[1]);
310 "Failed to close write end of standard error pipe: %s",
316 retval = close(stdin_pipe[0]);
319 log_warn(
LD_PROCESS,
"Failed to close read end of standard in pipe: %s",
355 if (BUG(unix_process->
waitpid == NULL))
363 ret = kill(unix_process->
pid, SIGTERM);
366 log_warn(
LD_PROCESS,
"Unable to terminate process: %s",
385 return (process_pid_t)unix_process->
pid;
509 if (event_add(handle->
event, NULL))
511 "Unable to add libevent event for handle.");
521 if (handle->
event == NULL)
524 if (event_del(handle->
event))
526 "Unable to delete libevent event for handle.");
536 if (event_add(handle->
event, NULL))
538 "Unable to add libevent event for handle.");
550 if (handle->
event == NULL)
553 if (event_del(handle->
event))
555 "Unable to delete libevent event for handle.");
591 event_callback_fn callback)
598 if (fcntl(handle->
fd, F_SETFL, O_NONBLOCK) < 0) {
599 log_warn(
LD_PROCESS,
"Unable mark Unix handle as non-blocking: %s",
634 "Unable to read data: %s", strerror(error));
668 log_warn(
LD_PROCESS,
"Unable to close standard in");
678 log_warn(
LD_PROCESS,
"Unable to close standard out");
688 log_warn(
LD_PROCESS,
"Unable to close standard error");
size_t buf_datalen(const buf_t *buf)
Header file for buffers.c.
int buf_read_from_pipe(buf_t *buf, int fd, size_t at_most, int *reached_eof, int *socket_error)
int buf_flush_to_pipe(buf_t *buf, int fd, size_t sz)
Header file for buffers_net.c.
Macro definitions for MIN, MAX, and CLAMP.
struct event_base * tor_libevent_get_base(void)
Header for compat_libevent.c.
void process_notify_event_stdout(process_t *process)
void process_notify_event_exit(process_t *process, process_exit_code_t exit_code)
void process_notify_event_stderr(process_t *process)
process_environment_t * process_get_environment(const process_t *process)
process_unix_t * process_get_unix_process(const process_t *process)
char ** process_get_argv(const process_t *process)
void process_notify_event_stdin(process_t *process)
#define PROCESS_MAX_WRITE
STATIC void stdin_write_callback(evutil_socket_t fd, short event, void *data)
int process_unix_write(process_t *process, buf_t *buffer)
bool process_unix_terminate(process_t *process)
STATIC void process_unix_setup_handle(process_t *process, process_unix_handle_t *handle, short flags, event_callback_fn callback)
int process_unix_read_stderr(process_t *process, buf_t *buffer)
process_pid_t process_unix_get_pid(process_t *process)
int process_unix_read_stdout(process_t *process, buf_t *buffer)
STATIC void stdout_read_callback(evutil_socket_t fd, short event, void *data)
STATIC void process_unix_start_writing(process_unix_handle_t *handle)
void process_unix_free_(process_unix_t *unix_process)
STATIC void process_unix_stop_reading(process_unix_handle_t *handle)
STATIC void stderr_read_callback(evutil_socket_t fd, short event, void *data)
STATIC void process_unix_waitpid_callback(int status, void *data)
process_unix_t * process_unix_new(void)
STATIC void process_unix_start_reading(process_unix_handle_t *handle)
STATIC int process_unix_read_handle(process_t *process, process_unix_handle_t *handle, buf_t *buffer)
STATIC void process_unix_stop_writing(process_unix_handle_t *handle)
process_status_t process_unix_exec(process_t *process)
STATIC bool process_unix_close_file_descriptors(process_unix_t *unix_process)
Header for process_unix.c.
char ** unixoid_environment_block
process_unix_handle_t stdin_handle
waitpid_callback_t * waitpid
process_unix_handle_t stderr_handle
process_unix_handle_t stdout_handle
Macros to manage assertions, fatal and non-fatal.
void clear_waitpid_callback(waitpid_callback_t *ent)