static void babysit (pid_t grandchild_pid, int parent_pipe) { int sigchld_pipe[2]; /* We don't exec, so we keep parent state, such as the pid that * _dbus_verbose() uses. Reset the pid here. */ _dbus_verbose_reset (); /* I thought SIGCHLD would just wake up the poll, but * that didn't seem to work, so added this pipe. * Probably the pipe is more likely to work on busted * operating systems anyhow. */ if (pipe (sigchld_pipe) < 0) { _dbus_warn ("Not enough file descriptors to create pipe in babysitter process\n"); exit (1); } babysit_sigchld_pipe = sigchld_pipe[WRITE_END]; #ifndef __SYMBIAN32__ _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler); #endif write_pid (parent_pipe, grandchild_pid); check_babysit_events (grandchild_pid, parent_pipe, 0); while (TRUE) { DBusPollFD pfds[2]; pfds[0].fd = parent_pipe; pfds[0].events = _DBUS_POLLIN; pfds[0].revents = 0; pfds[1].fd = sigchld_pipe[READ_END]; pfds[1].events = _DBUS_POLLIN; pfds[1].revents = 0; _dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1); if (pfds[0].revents != 0) { check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents); } else if (pfds[1].revents & _DBUS_POLLIN) { char b; read (sigchld_pipe[READ_END], &b, 1); /* do waitpid check */ check_babysit_events (grandchild_pid, parent_pipe, 0); } } exit (1); }
static void do_exec (int child_err_report_fd, char * const *argv, char * const *envp, DBusSpawnChildSetupFunc child_setup, void *user_data) { #ifdef DBUS_ENABLE_EMBEDDED_TESTS int i, max_open; #endif _dbus_verbose_reset (); _dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n", _dbus_getpid ()); if (child_setup) (* child_setup) (user_data); #ifdef DBUS_ENABLE_EMBEDDED_TESTS max_open = sysconf (_SC_OPEN_MAX); for (i = 3; i < max_open; i++) { int retval; if (i == child_err_report_fd) continue; retval = fcntl (i, F_GETFD); if (retval != -1 && !(retval & FD_CLOEXEC)) _dbus_warn ("Fd %d did not have the close-on-exec flag set!", i); } #endif if (envp == NULL) { _dbus_assert (environ != NULL); envp = environ; } execve (argv[0], argv, envp); /* Exec failed */ write_err_and_exit (child_err_report_fd, CHILD_EXEC_FAILED); }
static void do_exec (int child_err_report_fd, char **argv, DBusSpawnChildSetupFunc child_setup, void *user_data) { #ifdef DBUS_BUILD_TESTS int i, max_open; #endif _dbus_verbose_reset (); _dbus_verbose ("Child process has PID %lu\n", _dbus_getpid ()); if (child_setup) (* child_setup) (user_data); #ifdef DBUS_BUILD_TESTS max_open = sysconf (_SC_OPEN_MAX); for (i = 3; i < max_open; i++) { int retval; if (i == child_err_report_fd) continue; retval = fcntl (i, F_GETFD); if (retval != -1 && !(retval & FD_CLOEXEC)) _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i); } #endif #ifndef __SYMBIAN32__ execv (argv[0], argv); #endif /* Exec failed */ write_err_and_exit (child_err_report_fd, CHILD_EXEC_FAILED); }