void* sendChildOutputToSyslogThread(void *p) { int error = EXIT_SUCCESS; sigset_t blockedSignalsMask; outputToSyslogParam *params = (outputToSyslogParam*) p; char buffer[MAXLINE]; ssize_t n; sigemptyset(&blockedSignalsMask); sigaddset(&blockedSignalsMask, SIGCHLD); error = pthread_sigmask(SIG_BLOCK, &blockedSignalsMask, NULL); if (error != 0) { WARNING_MSG("pthread_sigmask error %d (%m)", error); } while ((n = read(params->pipe, buffer, sizeof (buffer))) > 0) { buffer[n] = '\0'; DEBUG_VAR(buffer, "%s"); __syslogex_pid_chk(params->pid, params->level, -1, buffer); } if (n != 0) { const int error = errno; ERROR_MSG("read from %d error %d (%m)", params->pipe, error); } CLOSE_PIPE(params->pipe); return NULL; }
static inline int execChild(const char *file, char *argv[], int stdoutWritePipe, int stderrWritePipe) { int error = EXIT_SUCCESS; if (dup2(stdoutWritePipe, STDOUT_FILENO) != -1) { /* close stdout and redirect it to the pipe */ if (dup2(stderrWritePipe, STDERR_FILENO) != -1) { /* close stderr and redirect it to the pipe */ //DEBUG_VAR(file,"%s"); //DEBUG_VAR(argv[0],"%s"); //usleep(500); if (execvp(file, argv)) { error = errno; ERROR_MSG("execvp error %d (%m)", error); } } else { int error = errno; ERROR_MSG("dup2 stderr error %d (%m)", error); } } else { int error = errno; ERROR_MSG("dup2 stdout error %d (%m)", error); } CLOSE_PIPE(stdoutWritePipe); CLOSE_PIPE(stderrWritePipe); return error; }
/* * This is the only use we have in mono/metadata !g_spawn_async_with_pipes (NULL, (char**)addr_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &child_pid, &ch_in, &ch_out, NULL, NULL) */ gboolean g_spawn_async_with_pipes (const gchar *working_directory, gchar **argv, gchar **envp, GSpawnFlags flags, GSpawnChildSetupFunc child_setup, gpointer user_data, GPid *child_pid, gint *standard_input, gint *standard_output, gint *standard_error, GError **error) { #ifdef G_OS_WIN32 #else pid_t pid; int info_pipe [2]; int in_pipe [2] = { -1, -1 }; int out_pipe [2] = { -1, -1 }; int err_pipe [2] = { -1, -1 }; int status; g_return_val_if_fail (argv != NULL, FALSE); /* Only mandatory arg */ if (!create_pipe (info_pipe, error)) return FALSE; if (standard_output && !create_pipe (out_pipe, error)) { CLOSE_PIPE (info_pipe); return FALSE; } if (standard_error && !create_pipe (err_pipe, error)) { CLOSE_PIPE (info_pipe); CLOSE_PIPE (out_pipe); return FALSE; } if (standard_input && !create_pipe (in_pipe, error)) { CLOSE_PIPE (info_pipe); CLOSE_PIPE (out_pipe); CLOSE_PIPE (err_pipe); return FALSE; } pid = fork (); if (pid == -1) { CLOSE_PIPE (info_pipe); CLOSE_PIPE (out_pipe); CLOSE_PIPE (err_pipe); CLOSE_PIPE (in_pipe); set_error ("%s", "Error in fork ()"); return FALSE; } if (pid == 0) { /* No zombie left behind */ if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) { pid = fork (); } if (pid != 0) { exit (pid == -1 ? 1 : 0); } else { gint i; int fd; gchar *arg0; gchar **actual_args; gint unused; close (info_pipe [0]); close (in_pipe [1]); close (out_pipe [0]); close (err_pipe [0]); /* when exec* succeeds, we want to close this fd, which will return * a 0 read on the parent. We're not supposed to keep it open forever. * If exec fails, we still can write the error to it before closing. */ fcntl (info_pipe [1], F_SETFD, FD_CLOEXEC); if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) { pid = getpid (); NO_INTR (unused, write_all (info_pipe [1], &pid, sizeof (pid_t))); } if (working_directory && chdir (working_directory) == -1) { int err = errno; NO_INTR (unused, write_all (info_pipe [1], &err, sizeof (int))); exit (0); } if (standard_output) { dup2 (out_pipe [1], STDOUT_FILENO); } else if ((flags & G_SPAWN_STDOUT_TO_DEV_NULL) != 0) { fd = open ("/dev/null", O_WRONLY); dup2 (fd, STDOUT_FILENO); } if (standard_error) { dup2 (err_pipe [1], STDERR_FILENO); } else if ((flags & G_SPAWN_STDERR_TO_DEV_NULL) != 0) { fd = open ("/dev/null", O_WRONLY); dup2 (fd, STDERR_FILENO); } if (standard_input) { dup2 (in_pipe [0], STDIN_FILENO); } else if ((flags & G_SPAWN_CHILD_INHERITS_STDIN) == 0) { fd = open ("/dev/null", O_RDONLY); dup2 (fd, STDIN_FILENO); } if ((flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN) != 0) { for (i = getdtablesize () - 1; i >= 3; i--) close (i); } actual_args = ((flags & G_SPAWN_FILE_AND_ARGV_ZERO) == 0) ? argv : argv + 1; if (envp == NULL) envp = environ; if (child_setup) child_setup (user_data); arg0 = argv [0]; if (!g_path_is_absolute (arg0) || (flags & G_SPAWN_SEARCH_PATH) != 0) { arg0 = g_find_program_in_path (argv [0]); if (arg0 == NULL) { int err = ENOENT; write_all (info_pipe [1], &err, sizeof (int)); exit (0); } } execve (arg0, actual_args, envp); write_all (info_pipe [1], &errno, sizeof (int)); exit (0); } } else if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) { int w; /* Wait for the first child if two are created */ NO_INTR (w, waitpid (pid, &status, 0)); if (status == 1 || w == -1) { CLOSE_PIPE (info_pipe); CLOSE_PIPE (out_pipe); CLOSE_PIPE (err_pipe); CLOSE_PIPE (in_pipe); set_error ("Error in fork (): %d", status); return FALSE; } } close (info_pipe [1]); close (in_pipe [0]); close (out_pipe [1]); close (err_pipe [1]); if ((flags & G_SPAWN_DO_NOT_REAP_CHILD) == 0) { int x; NO_INTR (x, read (info_pipe [0], &pid, sizeof (pid_t))); /* if we read < sizeof (pid_t)... */ } if (child_pid) { *child_pid = pid; } if (read (info_pipe [0], &status, sizeof (int)) != 0) { close (info_pipe [0]); close (in_pipe [0]); close (out_pipe [1]); close (err_pipe [1]); set_error_status (status, "Error in exec (%d -> %s)", status, strerror (status)); return FALSE; } close (info_pipe [0]); if (standard_input) *standard_input = in_pipe [1]; if (standard_output) *standard_output = out_pipe [0]; if (standard_error) *standard_error = err_pipe [0]; #endif return TRUE; }
gboolean g_spawn_command_line_sync (const gchar *command_line, gchar **standard_output, gchar **standard_error, gint *exit_status, GError **error) { #ifdef G_OS_WIN32 #else pid_t pid; gchar **argv; gint argc; int stdout_pipe [2] = { -1, -1 }; int stderr_pipe [2] = { -1, -1 }; int status; int res; if (!g_shell_parse_argv (command_line, &argc, &argv, error)) return FALSE; if (standard_output && !create_pipe (stdout_pipe, error)) return FALSE; if (standard_error && !create_pipe (stderr_pipe, error)) { if (standard_output) { CLOSE_PIPE (stdout_pipe); } return FALSE; } pid = fork (); if (pid == 0) { gint i; if (standard_output) { close (stdout_pipe [0]); dup2 (stdout_pipe [1], STDOUT_FILENO); } if (standard_error) { close (stderr_pipe [0]); dup2 (stderr_pipe [1], STDERR_FILENO); } for (i = getdtablesize () - 1; i >= 3; i--) close (i); /* G_SPAWN_SEARCH_PATH is always enabled for g_spawn_command_line_sync */ if (!g_path_is_absolute (argv [0])) { gchar *arg0; arg0 = g_find_program_in_path (argv [0]); if (arg0 == NULL) { exit (1); } //g_free (argv [0]); argv [0] = arg0; } execv (argv [0], argv); exit (1); /* TODO: What now? */ } g_strfreev (argv); if (standard_output) close (stdout_pipe [1]); if (standard_error) close (stderr_pipe [1]); if (standard_output || standard_error) { res = read_pipes (stdout_pipe [0], standard_output, stderr_pipe [0], standard_error, error); if (res) { waitpid (pid, &status, WNOHANG); /* avoid zombie */ return FALSE; } } NO_INTR (res, waitpid (pid, &status, 0)); /* TODO: What if error? */ if (WIFEXITED (status) && exit_status) { *exit_status = WEXITSTATUS (status); } #endif return TRUE; }