29#if defined(DBUS_WIN) || !defined(DBUS_UNIX) 
   30#error "This file only makes sense on Unix OSs" 
   33#include "dbus-spawn.h" 
   34#include "dbus-sysdeps-unix.h" 
   35#include "dbus-internals.h" 
   37#include "dbus-protocol.h" 
   52#include <systemd/sd-journal.h> 
   56# include <crt_externs.h> 
   57# define environ (*_NSGetEnviron ()) 
   58#elif !HAVE_DECL_ENVIRON 
   92  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
  101      to_read = 
sizeof (int) * n_ints_in_buf - bytes;
 
  109                    ((
char*)buf) + bytes,
 
  112      if (chunk < 0 && errno == EINTR)
 
  119                          "Failed to read from child pipe (%s)",
 
  120                          _dbus_strerror (errno));
 
  134  *n_ints_read = (int)(bytes / 
sizeof(
int));
 
  147  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
  156      to_read = 
sizeof (pid_t) - bytes;
 
  164                    ((
char*)buf) + bytes,
 
  166      if (chunk < 0 && errno == EINTR)
 
  173                          "Failed to read from child pipe (%s)",
 
  174                          _dbus_strerror (errno));
 
  269  DBusBabysitterFinishedFunc finished_cb;
 
 
  280_dbus_babysitter_new (
void)
 
  351      close_socket_to_babysitter (sitter);
 
  353      close_error_pipe_from_child (sitter);
 
  364          ret = waitpid (sitter->
sitter_pid, &status, WNOHANG);
 
  376                  ret = waitpid (sitter->
sitter_pid, &status, 0);
 
  378              while (_DBUS_UNLIKELY (ret < 0 && errno == EINTR));
 
  384                _dbus_warn (
"Babysitter process not available to be reaped; should not happen");
 
  386                _dbus_warn (
"Unexpected error %d in waitpid() for babysitter: %s",
 
  387                            errno, _dbus_strerror (errno));
 
  391              _dbus_verbose (
"Reaped %ld, waiting for babysitter %ld\n",
 
  394              if (WIFEXITED (sitter->
status))
 
  395                _dbus_verbose (
"Babysitter exited with status %d\n",
 
  396                               WEXITSTATUS (sitter->
status));
 
  397              else if (WIFSIGNALED (sitter->
status))
 
  398                _dbus_verbose (
"Babysitter received signal %d\n",
 
  399                               WTERMSIG (sitter->
status));
 
  401                _dbus_verbose (
"Babysitter exited abnormally\n");
 
 
  425  r = read_ints (fd, &what, 1, &got, &error);
 
  450        case CHILD_FORK_FAILED:
 
  451        case CHILD_EXEC_FAILED:
 
  455            r = read_ints (fd, &arg, 1, &got, &error);
 
  474                if (what == CHILD_EXITED)
 
  495                    _dbus_verbose (
"recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
 
  496                                   WIFEXITED (sitter->
status), WIFSIGNALED (sitter->
status),
 
  497                                   WEXITSTATUS (sitter->
status), WTERMSIG (sitter->
status));
 
  499                else if (what == CHILD_FORK_FAILED)
 
  503                    _dbus_verbose (
"recorded fork errnum %d\n", sitter->
errnum);
 
  505                else if (what == CHILD_EXEC_FAILED)
 
  509                    _dbus_verbose (
"recorded exec errnum %d\n", sitter->
errnum);
 
  518            r = read_pid (fd, &pid, &error);
 
  537            _dbus_verbose (
"recorded grandchild pid %d\n", sitter->
grandchild_pid);
 
  541          _dbus_warn (
"Unknown message received from babysitter process");
 
  552  _dbus_verbose (
"Closing babysitter\n");
 
  573  _dbus_verbose (
"Closing child error\n");
 
  601      _dbus_verbose (
"Reading data from babysitter\n");
 
  603        close_socket_to_babysitter (sitter);
 
  607      close_socket_to_babysitter (sitter);
 
  617      _dbus_verbose (
"Reading data from child error\n");
 
  619        close_error_pipe_from_child (sitter);
 
  623      close_error_pipe_from_child (sitter);
 
  636  descriptors_ready = 
FALSE;
 
  664      while (ret < 0 && errno == EINTR);
 
  666      if (ret == 0 && block)
 
  672          while (ret < 0 && errno == EINTR);
 
  677          descriptors_ready = 
TRUE;
 
  683                handle_error_pipe (sitter, fds[i].revents);
 
  685                handle_babysitter_socket (sitter, fds[i].revents);
 
  690  return descriptors_ready;
 
  697#define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter.fd >= 0 || (sitter)->error_pipe_from_child >= 0) 
  711    babysitter_iteration (sitter, 
TRUE);
 
  713  _dbus_verbose (
"Got child PID %ld for killing\n",
 
 
  733         babysitter_iteration (sitter, 
FALSE))
 
 
  760      !(WIFEXITED (sitter->
status)))
 
  763  *status = WEXITSTATUS (sitter->
status);
 
 
  790                      "Failed to execute program %s: %s",
 
  796                      "Failed to fork a new process %s: %s",
 
  801      if (WIFEXITED (sitter->
status))
 
  803                        "Process %s exited with status %d",
 
  805      else if (WIFSIGNALED (sitter->
status))
 
  807                        "Process %s received signal %d",
 
  811                        "Process %s exited abnormally",
 
  817                      "Process %s exited, reason unknown",
 
 
  852              unsigned int     condition,
 
  870    handle_error_pipe (sitter, revents);
 
  872    handle_babysitter_socket (sitter, revents);
 
  875         babysitter_iteration (sitter, 
FALSE))
 
  884      sitter->finished_cb != 
NULL)
 
  886      sitter->finished_cb (sitter, sitter->finished_data);
 
  887      sitter->finished_cb = 
NULL;
 
  910close_and_invalidate (
int *fd)
 
  934  retval = pipe2 (p, O_CLOEXEC);
 
  935  cloexec_done = retval >= 0;
 
  939  if (retval < 0 && errno == ENOSYS)
 
  945  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
  951                      "Failed to create pipe for communicating with child process (%s)",
 
  952                      _dbus_strerror (errno));
 
  968do_write (
int fd, 
const void *buf, 
size_t count)
 
  970  size_t bytes_written;
 
  977  ret = write (fd, ((
const char*)buf) + bytes_written, count - bytes_written);
 
  990    bytes_written += ret;
 
  992  if (bytes_written < count)
 
  996static void write_err_and_exit (
int fd, 
int msg) _DBUS_GNUC_NORETURN;
 
  999write_err_and_exit (
int fd, 
int msg)
 
 1003  do_write (fd, &msg, 
sizeof (msg));
 
 1004  do_write (fd, &en, 
sizeof (en));
 
 1010write_pid (
int fd, pid_t pid)
 
 1012  int msg = CHILD_PID;
 
 1014  do_write (fd, &msg, 
sizeof (msg));
 
 1015  do_write (fd, &pid, 
sizeof (pid));
 
 1018static void write_status_and_exit (
int fd, 
int status) _DBUS_GNUC_NORETURN;
 
 1021write_status_and_exit (
int fd, 
int status)
 
 1023  int msg = CHILD_EXITED;
 
 1025  do_write (fd, &msg, 
sizeof (msg));
 
 1026  do_write (fd, &status, 
sizeof (status));
 
 1031static void do_exec (
int                       child_err_report_fd,
 
 1034                     DBusSpawnChildSetupFunc   child_setup,
 
 1035                     void                     *user_data) _DBUS_GNUC_NORETURN;
 
 1038do_exec (
int                       child_err_report_fd,
 
 1041         DBusSpawnChildSetupFunc   child_setup,
 
 1044#ifdef DBUS_ENABLE_EMBEDDED_TESTS 
 1048  _dbus_verbose_reset ();
 
 1053    (* child_setup) (user_data);
 
 1055#ifdef DBUS_ENABLE_EMBEDDED_TESTS 
 1056  max_open = sysconf (_SC_OPEN_MAX);
 
 1061  if (max_open > 1024)
 
 1064  for (i = 3; i < max_open; i++)
 
 1068      if (i == child_err_report_fd)
 
 1071      retval = fcntl (i, F_GETFD);
 
 1073      if (retval != -1 && !(retval & FD_CLOEXEC))
 
 1075          char description[256] = { 0 };
 
 1076          char proc_self_fd[256] = { 0 };
 
 1077          size_t description_length = 
sizeof (description) - 1;
 
 1079          snprintf (proc_self_fd, 
sizeof (proc_self_fd) - 1,
 
 1080                    "/proc/self/fd/%d", i);
 
 1081          proc_self_fd[
sizeof (proc_self_fd) - 1] = 
'\0';
 
 1083          if (readlink (proc_self_fd, description, description_length) <= 0)
 
 1084            snprintf (description, 
sizeof (description) - 1, 
"(unknown)");
 
 1086          description[
sizeof (description) - 1] = 
'\0';
 
 1087          _dbus_warn (
"Fd %d \"%s\" did not have the close-on-exec flag set!",
 
 1100  execve (argv[0], argv, envp);
 
 1103  write_err_and_exit (child_err_report_fd,
 
 1108check_babysit_events (pid_t grandchild_pid,
 
 1117      ret = waitpid (grandchild_pid, &status, WNOHANG);
 
 1122  while (ret < 0 && errno == EINTR);
 
 1126      _dbus_verbose (
"no child exited\n");
 
 1133      _dbus_warn (
"unexpected waitpid() failure in check_babysit_events(): %s",
 
 1134                  _dbus_strerror (errno));
 
 1137  else if (ret == grandchild_pid)
 
 1140      _dbus_verbose (
"reaped child pid %ld\n", (
long) ret);
 
 1142      write_status_and_exit (parent_pipe, status);
 
 1146      _dbus_warn (
"waitpid() reaped pid %d that we've never heard of",
 
 1153      _dbus_verbose (
"babysitter got POLLIN from parent pipe\n");
 
 1159      _dbus_verbose (
"babysitter got POLLERR or POLLHUP from parent\n");
 
 1166static int babysit_sigchld_pipe = -1;
 
 1169babysit_signal_handler (
int signo)
 
 1173  int saved_errno = errno;
 
 1177  if (write (babysit_sigchld_pipe, &b, 1) <= 0)
 
 1181  errno = saved_errno;
 
 1184static void babysit (pid_t grandchild_pid,
 
 1185                     int   parent_pipe) _DBUS_GNUC_NORETURN;
 
 1188babysit (pid_t grandchild_pid,
 
 1191  int sigchld_pipe[2];
 
 1196  _dbus_verbose_reset ();
 
 1203  if (pipe (sigchld_pipe) < 0)
 
 1205      _dbus_warn (
"Not enough file descriptors to create pipe in babysitter process");
 
 1209  babysit_sigchld_pipe = sigchld_pipe[
WRITE_END];
 
 1213  write_pid (parent_pipe, grandchild_pid);
 
 1215  check_babysit_events (grandchild_pid, parent_pipe, 0);
 
 1221      pfds[0].
fd = parent_pipe;
 
 1231          _dbus_warn (
"_dbus_poll() error: %s", strerror (errno));
 
 1235      if (pfds[0].revents != 0)
 
 1237          check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
 
 1242          if (read (sigchld_pipe[
READ_END], &b, 1) == -1)
 
 1247          check_babysit_events (grandchild_pid, parent_pipe, 0);
 
 1280                                   const char               *log_name,
 
 1283                                   DBusSpawnFlags            flags,
 
 1284                                   DBusSpawnChildSetupFunc   child_setup,
 
 1289  int child_err_report_pipe[2] = { -1, -1 };
 
 1290  DBusSocket babysitter_pipe[2] = { DBUS_SOCKET_INIT, DBUS_SOCKET_INIT };
 
 1295  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
 1298  if (sitter_p != 
NULL)
 
 1303  sitter = _dbus_babysitter_new ();
 
 1314      goto cleanup_and_fail;
 
 1323      goto cleanup_and_fail;
 
 1326  if (!make_pipe (child_err_report_pipe, error))
 
 1327    goto cleanup_and_fail;
 
 1330    goto cleanup_and_fail;
 
 1343      goto cleanup_and_fail;
 
 1355      goto cleanup_and_fail;
 
 1364      goto cleanup_and_fail;
 
 1376      goto cleanup_and_fail;
 
 1379  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
 1381  if (flags & DBUS_SPAWN_SILENCE_OUTPUT)
 
 1383      fd_out = open (
"/dev/null", O_RDONLY);
 
 1388                          "Failed to open /dev/null: %s",
 
 1389                          _dbus_strerror (errno));
 
 1390          goto cleanup_and_fail;
 
 1398        goto cleanup_and_fail;
 
 1401  else if (flags & DBUS_SPAWN_REDIRECT_OUTPUT)
 
 1407      fd_out = sd_journal_stream_fd (sitter->
log_name, LOG_INFO, 
FALSE);
 
 1408      fd_err = sd_journal_stream_fd (sitter->
log_name, LOG_WARNING, 
FALSE);
 
 1423                      "Failed to fork (%s)",
 
 1424                      _dbus_strerror (errno));
 
 1425      goto cleanup_and_fail;
 
 1435      signal (SIGPIPE, SIG_DFL);
 
 1438      close_and_invalidate (&child_err_report_pipe[
READ_END]);
 
 1439      close_and_invalidate (&babysitter_pipe[0].fd);
 
 1445      grandchild_pid = fork ();
 
 1447      if (grandchild_pid < 0)
 
 1449          write_err_and_exit (babysitter_pipe[1].fd,
 
 1453      else if (grandchild_pid == 0)
 
 1463          signal (SIGPIPE, SIG_IGN);
 
 1465          close_and_invalidate (&babysitter_pipe[1].fd);
 
 1470            dup2 (fd_out, STDOUT_FILENO);
 
 1472            dup2 (fd_err, STDERR_FILENO);
 
 1473          close_and_invalidate (&fd_out);
 
 1474          close_and_invalidate (&fd_err);
 
 1476          do_exec (child_err_report_pipe[
WRITE_END],
 
 1479                   child_setup, user_data);
 
 1484          close_and_invalidate (&child_err_report_pipe[
WRITE_END]);
 
 1485          close_and_invalidate (&fd_out);
 
 1486          close_and_invalidate (&fd_err);
 
 1487          babysit (grandchild_pid, babysitter_pipe[1].fd);
 
 1494      close_and_invalidate (&child_err_report_pipe[
WRITE_END]);
 
 1495      close_and_invalidate (&babysitter_pipe[1].fd);
 
 1496      close_and_invalidate (&fd_out);
 
 1497      close_and_invalidate (&fd_err);
 
 1500      babysitter_pipe[0].fd = -1;
 
 1503      child_err_report_pipe[
READ_END] = -1;
 
 1507      if (sitter_p != 
NULL)
 
 1512      _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
 1519  _DBUS_ASSERT_ERROR_IS_SET (error);
 
 1521  close_and_invalidate (&child_err_report_pipe[
READ_END]);
 
 1522  close_and_invalidate (&child_err_report_pipe[
WRITE_END]);
 
 1523  close_and_invalidate (&babysitter_pipe[0].fd);
 
 1524  close_and_invalidate (&babysitter_pipe[1].fd);
 
 1525  close_and_invalidate (&fd_out);
 
 1526  close_and_invalidate (&fd_err);
 
 
 1536                                       DBusBabysitterFinishedFunc  finished,
 
 1539  sitter->finished_cb = finished;
 
 1540  sitter->finished_data = user_data;
 
 1549    babysitter_iteration (sitter, 
TRUE);
 
void(* DBusWatchToggledFunction)(DBusWatch *watch, void *data)
Called when dbus_watch_get_enabled() may return a different value than it did before.
dbus_bool_t(* DBusAddWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus needs a new watch to be monitored by the main loop.
void(* DBusRemoveWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus no longer needs a watch to be monitored by the main loop.
@ DBUS_WATCH_READABLE
As in POLLIN.
@ DBUS_WATCH_HANGUP
As in POLLHUP (can't watch for it, but can be present in current state passed to dbus_watch_handle())...
@ DBUS_WATCH_ERROR
As in POLLERR (can't watch for this, but can be present in current state passed to dbus_watch_handle(...
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
dbus_bool_t _dbus_babysitter_get_child_exit_status(DBusBabysitter *sitter, int *status)
Gets the exit status of the child.
#define READ_END
Helps remember which end of the pipe is which.
#define WRITE_END
Helps remember which end of the pipe is which.
void _dbus_babysitter_unref(DBusBabysitter *sitter)
Decrement the reference count on the babysitter object.
const char * _dbus_error_from_errno(int error_number)
Converts a UNIX errno, or Windows errno or WinSock error value into a DBusError name.
dbus_bool_t _dbus_babysitter_get_child_exited(DBusBabysitter *sitter)
Checks whether the child has exited, without blocking.
dbus_bool_t _dbus_babysitter_set_watch_functions(DBusBabysitter *sitter, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets watch functions to notify us when the babysitter object needs to read/write file descriptors.
char * _dbus_strdup(const char *str)
Duplicates a string.
void _dbus_babysitter_set_child_exit_error(DBusBabysitter *sitter, DBusError *error)
Sets the DBusError with an explanation of why the spawned child process exited (on a signal,...
ReadStatus
Enumeration for status of a read()
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
void _dbus_babysitter_kill_child(DBusBabysitter *sitter)
Blocks until the babysitter process gives us the PID of the spawned grandchild, then kills the spawne...
DBusBabysitter * _dbus_babysitter_ref(DBusBabysitter *sitter)
Increment the reference count on the babysitter object.
dbus_bool_t _dbus_spawn_async_with_babysitter(DBusBabysitter **sitter_p, const char *log_name, char *const *argv, char *const *env, DBusSpawnFlags flags, DBusSpawnChildSetupFunc child_setup, void *user_data, DBusError *error)
Spawns a new process.
#define LIVE_CHILDREN(sitter)
Macro returns TRUE if the babysitter still has live sockets open to the babysitter child or the grand...
@ READ_STATUS_OK
Read succeeded.
@ READ_STATUS_EOF
EOF returned.
@ READ_STATUS_ERROR
Some kind of error.
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
#define DBUS_ERROR_SPAWN_CHILD_EXITED
While starting a new process, the child exited with a status code.
#define DBUS_ERROR_SPAWN_CHILD_SIGNALED
While starting a new process, the child exited on a signal.
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
#define DBUS_ERROR_SPAWN_FAILED
While starting a new process, something went wrong.
#define DBUS_ERROR_SPAWN_FORK_FAILED
While starting a new process, the fork() call failed.
dbus_bool_t _dbus_reset_oom_score_adj(const char **error_str_p)
If the current process has been protected from the Linux OOM killer (the oom_score_adj process parame...
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
void _dbus_set_signal_handler(int sig, DBusSignalHandler handler)
Installs a UNIX signal handler.
int _dbus_dup(int fd, DBusError *error)
Duplicates a file descriptor.
void _dbus_fd_set_close_on_exec(int fd)
Sets the file descriptor to be close on exec.
#define _DBUS_POLLERR
Error condition.
dbus_bool_t _dbus_socketpair(DBusSocket *fd1, DBusSocket *fd2, dbus_bool_t blocking, DBusError *error)
Creates pair of connect sockets (as in socketpair()).
dbus_pid_t _dbus_getpid(void)
Gets our process ID.
#define _DBUS_POLLHUP
Hung up.
#define _DBUS_POLLIN
There is data to read.
dbus_bool_t _dbus_close_socket(DBusSocket *fd, DBusError *error)
Closes a socket and invalidates it.
int _dbus_poll(DBusPollFD *fds, int n_fds, int timeout_milliseconds)
Wrapper for poll().
#define DBUS_PID_FORMAT
an appropriate printf format for dbus_pid_t
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
dbus_bool_t _dbus_watch_list_add_watch(DBusWatchList *watch_list, DBusWatch *watch)
Adds a new watch to the watch list, invoking the application DBusAddWatchFunction if appropriate.
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
dbus_bool_t _dbus_watch_list_set_functions(DBusWatchList *watch_list, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets the watch functions.
DBusWatch * _dbus_watch_new(DBusPollable fd, unsigned int flags, dbus_bool_t enabled, DBusWatchHandler handler, void *data, DBusFreeFunction free_data_function)
Creates a new DBusWatch.
void _dbus_watch_unref(DBusWatch *watch)
Decrements the reference count of a DBusWatch object and finalizes the object if the count reaches ze...
void _dbus_watch_list_remove_watch(DBusWatchList *watch_list, DBusWatch *watch)
Removes a watch from the watch list, invoking the application's DBusRemoveWatchFunction if appropriat...
void _dbus_watch_invalidate(DBusWatch *watch)
Clears the file descriptor from a now-invalid watch object so that no one tries to use it.
DBUS_EXPORT int dbus_watch_get_socket(DBusWatch *watch)
Returns a socket to be watched, on UNIX this will return -1 if our transport is not socket-based so d...
Babysitter implementation details.
DBusWatch * sitter_watch
Sitter pipe watch.
unsigned int have_exec_errnum
True if we have an error code from exec()
DBusSocket socket_to_babysitter
Connection to the babysitter process.
int status
Exit status code.
unsigned int have_child_status
True if child status has been reaped.
char * log_name
the name under which to log messages about this process being spawned
pid_t sitter_pid
PID Of the babysitter.
int error_pipe_from_child
Connection to the process that does the exec()
int refcount
Reference count.
DBusWatchList * watches
Watches.
DBusWatch * error_watch
Error pipe watch.
pid_t grandchild_pid
PID of the grandchild.
unsigned int have_fork_errnum
True if we have an error code from fork()
Object representing an exception.
const char * message
public error message field
short events
Events to poll for.
short revents
Events that occurred.
DBusPollable fd
File descriptor.
DBusWatchList implementation details.
Implementation of DBusWatch.