D-Bus  1.7.10
dbus-spawn.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-spawn.c Wrapper around fork/exec
3  *
4  * Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
5  * Copyright (C) 2003 CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 #include <config.h>
26 
27 #include "dbus-spawn.h"
28 #include "dbus-sysdeps-unix.h"
29 #include "dbus-internals.h"
30 #include "dbus-test.h"
31 #include "dbus-protocol.h"
32 
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <signal.h>
36 #include <sys/wait.h>
37 #include <stdlib.h>
38 #ifdef HAVE_ERRNO_H
39 #include <errno.h>
40 #endif
41 #ifdef HAVE_SYSTEMD
42 #include <systemd/sd-journal.h>
43 #endif
44 
45 extern char **environ;
46 
52 /*
53  * I'm pretty sure this whole spawn file could be made simpler,
54  * if you thought about it a bit.
55  */
56 
60 typedef enum
61 {
65 } ReadStatus;
66 
67 static ReadStatus
68 read_ints (int fd,
69  int *buf,
70  int n_ints_in_buf,
71  int *n_ints_read,
72  DBusError *error)
73 {
74  size_t bytes = 0;
75  ReadStatus retval;
76 
77  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
78 
79  retval = READ_STATUS_OK;
80 
81  while (TRUE)
82  {
83  ssize_t chunk;
84  size_t to_read;
85 
86  to_read = sizeof (int) * n_ints_in_buf - bytes;
87 
88  if (to_read == 0)
89  break;
90 
91  again:
92 
93  chunk = read (fd,
94  ((char*)buf) + bytes,
95  to_read);
96 
97  if (chunk < 0 && errno == EINTR)
98  goto again;
99 
100  if (chunk < 0)
101  {
102  dbus_set_error (error,
104  "Failed to read from child pipe (%s)",
105  _dbus_strerror (errno));
106 
107  retval = READ_STATUS_ERROR;
108  break;
109  }
110  else if (chunk == 0)
111  {
112  retval = READ_STATUS_EOF;
113  break; /* EOF */
114  }
115  else /* chunk > 0 */
116  bytes += chunk;
117  }
118 
119  *n_ints_read = (int)(bytes / sizeof(int));
120 
121  return retval;
122 }
123 
124 static ReadStatus
125 read_pid (int fd,
126  pid_t *buf,
127  DBusError *error)
128 {
129  size_t bytes = 0;
130  ReadStatus retval;
131 
132  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
133 
134  retval = READ_STATUS_OK;
135 
136  while (TRUE)
137  {
138  ssize_t chunk;
139  size_t to_read;
140 
141  to_read = sizeof (pid_t) - bytes;
142 
143  if (to_read == 0)
144  break;
145 
146  again:
147 
148  chunk = read (fd,
149  ((char*)buf) + bytes,
150  to_read);
151  if (chunk < 0 && errno == EINTR)
152  goto again;
153 
154  if (chunk < 0)
155  {
156  dbus_set_error (error,
158  "Failed to read from child pipe (%s)",
159  _dbus_strerror (errno));
160 
161  retval = READ_STATUS_ERROR;
162  break;
163  }
164  else if (chunk == 0)
165  {
166  retval = READ_STATUS_EOF;
167  break; /* EOF */
168  }
169  else /* chunk > 0 */
170  bytes += chunk;
171  }
172 
173  return retval;
174 }
175 
176 /* The implementation uses an intermediate child between the main process
177  * and the grandchild. The grandchild is our spawned process. The intermediate
178  * child is a babysitter process; it keeps track of when the grandchild
179  * exits/crashes, and reaps the grandchild.
180  *
181  * We automatically reap the babysitter process, killing it if necessary,
182  * when the DBusBabysitter's refcount goes to zero.
183  *
184  * Processes:
185  *
186  * main process
187  * | fork() A
188  * \- babysitter
189  * | fork () B
190  * \- grandchild --> exec --> spawned process
191  *
192  * IPC:
193  * child_err_report_pipe
194  * /-----------<---------<--------------\
195  * | ^
196  * v |
197  * main process babysitter grandchild
198  * ^ ^
199  * v v
200  * \-------<->-------/
201  * babysitter_pipe
202  *
203  * child_err_report_pipe is genuinely a pipe.
204  * The READ_END (also called error_pipe_from_child) is used in the main
205  * process. The WRITE_END (also called child_err_report_fd) is used in
206  * the grandchild process.
207  *
208  * On failure, the grandchild process sends CHILD_EXEC_FAILED + errno.
209  * On success, the pipe just closes (because it's close-on-exec) without
210  * sending any bytes.
211  *
212  * babysitter_pipe is mis-named: it's really a bidirectional socketpair.
213  * The [0] end (also called socket_to_babysitter) is used in the main
214  * process, the [1] end (also called parent_pipe) is used in the babysitter.
215  *
216  * If the fork() labelled B in the diagram above fails, the babysitter sends
217  * CHILD_FORK_FAILED + errno.
218  * On success, the babysitter sends CHILD_PID + the grandchild's pid.
219  * On SIGCHLD, the babysitter sends CHILD_EXITED + the exit status.
220  * The main process doesn't explicitly send anything, but when it exits,
221  * the babysitter gets POLLHUP or POLLERR.
222  */
223 
224 /* Messages from children to parents */
225 enum
226 {
227  CHILD_EXITED, /* This message is followed by the exit status int */
228  CHILD_FORK_FAILED, /* Followed by errno */
229  CHILD_EXEC_FAILED, /* Followed by errno */
230  CHILD_PID /* Followed by pid_t */
231 };
232 
236 struct DBusBabysitter
237 {
238  int refcount;
240  char *log_name;
246  pid_t sitter_pid;
254  DBusBabysitterFinishedFunc finished_cb;
255  void *finished_data;
256 
257  int errnum;
258  int status;
259  unsigned int have_child_status : 1;
260  unsigned int have_fork_errnum : 1;
261  unsigned int have_exec_errnum : 1;
262 };
263 
264 static DBusBabysitter*
265 _dbus_babysitter_new (void)
266 {
267  DBusBabysitter *sitter;
268 
269  sitter = dbus_new0 (DBusBabysitter, 1);
270  if (sitter == NULL)
271  return NULL;
272 
273  sitter->refcount = 1;
274 
275  sitter->socket_to_babysitter = -1;
276  sitter->error_pipe_from_child = -1;
277 
278  sitter->sitter_pid = -1;
279  sitter->grandchild_pid = -1;
280 
281  sitter->watches = _dbus_watch_list_new ();
282  if (sitter->watches == NULL)
283  goto failed;
284 
285  return sitter;
286 
287  failed:
288  _dbus_babysitter_unref (sitter);
289  return NULL;
290 }
291 
300 {
301  _dbus_assert (sitter != NULL);
302  _dbus_assert (sitter->refcount > 0);
303 
304  sitter->refcount += 1;
305 
306  return sitter;
307 }
308 
309 static void close_socket_to_babysitter (DBusBabysitter *sitter);
310 static void close_error_pipe_from_child (DBusBabysitter *sitter);
311 
320 void
322 {
323  _dbus_assert (sitter != NULL);
324  _dbus_assert (sitter->refcount > 0);
325 
326  sitter->refcount -= 1;
327  if (sitter->refcount == 0)
328  {
329  /* If we haven't forked other babysitters
330  * since this babysitter and socket were
331  * created then this close will cause the
332  * babysitter to wake up from poll with
333  * a hangup and then the babysitter will
334  * quit itself.
335  */
336  close_socket_to_babysitter (sitter);
337 
338  close_error_pipe_from_child (sitter);
339 
340  if (sitter->sitter_pid > 0)
341  {
342  int status;
343  int ret;
344 
345  /* It's possible the babysitter died on its own above
346  * from the close, or was killed randomly
347  * by some other process, so first try to reap it
348  */
349  ret = waitpid (sitter->sitter_pid, &status, WNOHANG);
350 
351  /* If we couldn't reap the child then kill it, and
352  * try again
353  */
354  if (ret == 0)
355  kill (sitter->sitter_pid, SIGKILL);
356 
357  if (ret == 0)
358  {
359  do
360  {
361  ret = waitpid (sitter->sitter_pid, &status, 0);
362  }
363  while (_DBUS_UNLIKELY (ret < 0 && errno == EINTR));
364  }
365 
366  if (ret < 0)
367  {
368  if (errno == ECHILD)
369  _dbus_warn ("Babysitter process not available to be reaped; should not happen\n");
370  else
371  _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n",
372  errno, _dbus_strerror (errno));
373  }
374  else
375  {
376  _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n",
377  (long) ret, (long) sitter->sitter_pid);
378 
379  if (WIFEXITED (sitter->status))
380  _dbus_verbose ("Babysitter exited with status %d\n",
381  WEXITSTATUS (sitter->status));
382  else if (WIFSIGNALED (sitter->status))
383  _dbus_verbose ("Babysitter received signal %d\n",
384  WTERMSIG (sitter->status));
385  else
386  _dbus_verbose ("Babysitter exited abnormally\n");
387  }
388 
389  sitter->sitter_pid = -1;
390  }
391 
392  if (sitter->watches)
393  _dbus_watch_list_free (sitter->watches);
394 
395  dbus_free (sitter->log_name);
396 
397  dbus_free (sitter);
398  }
399 }
400 
401 static ReadStatus
402 read_data (DBusBabysitter *sitter,
403  int fd)
404 {
405  int what;
406  int got;
407  DBusError error = DBUS_ERROR_INIT;
408  ReadStatus r;
409 
410  r = read_ints (fd, &what, 1, &got, &error);
411 
412  switch (r)
413  {
414  case READ_STATUS_ERROR:
415  _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message);
416  dbus_error_free (&error);
417  return r;
418 
419  case READ_STATUS_EOF:
420  return r;
421 
422  case READ_STATUS_OK:
423  break;
424  }
425 
426  if (got == 1)
427  {
428  switch (what)
429  {
430  case CHILD_EXITED:
431  case CHILD_FORK_FAILED:
432  case CHILD_EXEC_FAILED:
433  {
434  int arg;
435 
436  r = read_ints (fd, &arg, 1, &got, &error);
437 
438  switch (r)
439  {
440  case READ_STATUS_ERROR:
441  _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message);
442  dbus_error_free (&error);
443  return r;
444  case READ_STATUS_EOF:
445  return r;
446  case READ_STATUS_OK:
447  break;
448  }
449 
450  if (got == 1)
451  {
452  if (what == CHILD_EXITED)
453  {
454  sitter->have_child_status = TRUE;
455  sitter->status = arg;
456  sitter->errnum = 0;
457  _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
458  WIFEXITED (sitter->status), WIFSIGNALED (sitter->status),
459  WEXITSTATUS (sitter->status), WTERMSIG (sitter->status));
460  }
461  else if (what == CHILD_FORK_FAILED)
462  {
463  sitter->have_fork_errnum = TRUE;
464  sitter->errnum = arg;
465  _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum);
466  }
467  else if (what == CHILD_EXEC_FAILED)
468  {
469  sitter->have_exec_errnum = TRUE;
470  sitter->errnum = arg;
471  _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum);
472  }
473  }
474  }
475  break;
476  case CHILD_PID:
477  {
478  pid_t pid = -1;
479 
480  r = read_pid (fd, &pid, &error);
481 
482  switch (r)
483  {
484  case READ_STATUS_ERROR:
485  _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message);
486  dbus_error_free (&error);
487  return r;
488  case READ_STATUS_EOF:
489  return r;
490  case READ_STATUS_OK:
491  break;
492  }
493 
494  sitter->grandchild_pid = pid;
495 
496  _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid);
497  }
498  break;
499  default:
500  _dbus_warn ("Unknown message received from babysitter process\n");
501  break;
502  }
503  }
504 
505  return r;
506 }
507 
508 static void
509 close_socket_to_babysitter (DBusBabysitter *sitter)
510 {
511  _dbus_verbose ("Closing babysitter\n");
512 
513  if (sitter->sitter_watch != NULL)
514  {
515  _dbus_assert (sitter->watches != NULL);
519  sitter->sitter_watch = NULL;
520  }
521 
522  if (sitter->socket_to_babysitter >= 0)
523  {
525  sitter->socket_to_babysitter = -1;
526  }
527 }
528 
529 static void
530 close_error_pipe_from_child (DBusBabysitter *sitter)
531 {
532  _dbus_verbose ("Closing child error\n");
533 
534  if (sitter->error_watch != NULL)
535  {
536  _dbus_assert (sitter->watches != NULL);
539  _dbus_watch_unref (sitter->error_watch);
540  sitter->error_watch = NULL;
541  }
542 
543  if (sitter->error_pipe_from_child >= 0)
544  {
546  sitter->error_pipe_from_child = -1;
547  }
548 }
549 
550 static void
551 handle_babysitter_socket (DBusBabysitter *sitter,
552  int revents)
553 {
554  /* Even if we have POLLHUP, we want to keep reading
555  * data until POLLIN goes away; so this function only
556  * looks at HUP/ERR if no IN is set.
557  */
558  if (revents & _DBUS_POLLIN)
559  {
560  _dbus_verbose ("Reading data from babysitter\n");
561  if (read_data (sitter, sitter->socket_to_babysitter) != READ_STATUS_OK)
562  close_socket_to_babysitter (sitter);
563  }
564  else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
565  {
566  close_socket_to_babysitter (sitter);
567  }
568 }
569 
570 static void
571 handle_error_pipe (DBusBabysitter *sitter,
572  int revents)
573 {
574  if (revents & _DBUS_POLLIN)
575  {
576  _dbus_verbose ("Reading data from child error\n");
577  if (read_data (sitter, sitter->error_pipe_from_child) != READ_STATUS_OK)
578  close_error_pipe_from_child (sitter);
579  }
580  else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
581  {
582  close_error_pipe_from_child (sitter);
583  }
584 }
585 
586 /* returns whether there were any poll events handled */
587 static dbus_bool_t
588 babysitter_iteration (DBusBabysitter *sitter,
589  dbus_bool_t block)
590 {
591  DBusPollFD fds[2];
592  int i;
593  dbus_bool_t descriptors_ready;
594 
595  descriptors_ready = FALSE;
596 
597  i = 0;
598 
599  if (sitter->error_pipe_from_child >= 0)
600  {
601  fds[i].fd = sitter->error_pipe_from_child;
602  fds[i].events = _DBUS_POLLIN;
603  fds[i].revents = 0;
604  ++i;
605  }
606 
607  if (sitter->socket_to_babysitter >= 0)
608  {
609  fds[i].fd = sitter->socket_to_babysitter;
610  fds[i].events = _DBUS_POLLIN;
611  fds[i].revents = 0;
612  ++i;
613  }
614 
615  if (i > 0)
616  {
617  int ret;
618 
619  do
620  {
621  ret = _dbus_poll (fds, i, 0);
622  }
623  while (ret < 0 && errno == EINTR);
624 
625  if (ret == 0 && block)
626  {
627  do
628  {
629  ret = _dbus_poll (fds, i, -1);
630  }
631  while (ret < 0 && errno == EINTR);
632  }
633 
634  if (ret > 0)
635  {
636  descriptors_ready = TRUE;
637 
638  while (i > 0)
639  {
640  --i;
641  if (fds[i].fd == sitter->error_pipe_from_child)
642  handle_error_pipe (sitter, fds[i].revents);
643  else if (fds[i].fd == sitter->socket_to_babysitter)
644  handle_babysitter_socket (sitter, fds[i].revents);
645  }
646  }
647  }
648 
649  return descriptors_ready;
650 }
651 
656 #define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter >= 0 || (sitter)->error_pipe_from_child >= 0)
657 
664 void
666 {
667  /* be sure we have the PID of the child */
668  while (LIVE_CHILDREN (sitter) &&
669  sitter->grandchild_pid == -1)
670  babysitter_iteration (sitter, TRUE);
671 
672  _dbus_verbose ("Got child PID %ld for killing\n",
673  (long) sitter->grandchild_pid);
674 
675  if (sitter->grandchild_pid == -1)
676  return; /* child is already dead, or we're so hosed we'll never recover */
677 
678  kill (sitter->grandchild_pid, SIGKILL);
679 }
680 
688 {
689 
690  /* Be sure we're up-to-date */
691  while (LIVE_CHILDREN (sitter) &&
692  babysitter_iteration (sitter, FALSE))
693  ;
694 
695  /* We will have exited the babysitter when the child has exited */
696  return sitter->socket_to_babysitter < 0;
697 }
698 
713  int *status)
714 {
715  if (!_dbus_babysitter_get_child_exited (sitter))
716  _dbus_assert_not_reached ("Child has not exited");
717 
718  if (!sitter->have_child_status ||
719  !(WIFEXITED (sitter->status)))
720  return FALSE;
721 
722  *status = WEXITSTATUS (sitter->status);
723  return TRUE;
724 }
725 
735 void
737  DBusError *error)
738 {
739  if (!_dbus_babysitter_get_child_exited (sitter))
740  return;
741 
742  /* Note that if exec fails, we will also get a child status
743  * from the babysitter saying the child exited,
744  * so we need to give priority to the exec error
745  */
746  if (sitter->have_exec_errnum)
747  {
749  "Failed to execute program %s: %s",
750  sitter->log_name, _dbus_strerror (sitter->errnum));
751  }
752  else if (sitter->have_fork_errnum)
753  {
755  "Failed to fork a new process %s: %s",
756  sitter->log_name, _dbus_strerror (sitter->errnum));
757  }
758  else if (sitter->have_child_status)
759  {
760  if (WIFEXITED (sitter->status))
762  "Process %s exited with status %d",
763  sitter->log_name, WEXITSTATUS (sitter->status));
764  else if (WIFSIGNALED (sitter->status))
766  "Process %s received signal %d",
767  sitter->log_name, WTERMSIG (sitter->status));
768  else
770  "Process %s exited abnormally",
771  sitter->log_name);
772  }
773  else
774  {
776  "Process %s exited, reason unknown",
777  sitter->log_name);
778  }
779 }
780 
795  DBusAddWatchFunction add_function,
796  DBusRemoveWatchFunction remove_function,
797  DBusWatchToggledFunction toggled_function,
798  void *data,
799  DBusFreeFunction free_data_function)
800 {
801  return _dbus_watch_list_set_functions (sitter->watches,
802  add_function,
803  remove_function,
804  toggled_function,
805  data,
806  free_data_function);
807 }
808 
809 static dbus_bool_t
810 handle_watch (DBusWatch *watch,
811  unsigned int condition,
812  void *data)
813 {
814  DBusBabysitter *sitter = _dbus_babysitter_ref (data);
815  int revents;
816  int fd;
817 
818  revents = 0;
819  if (condition & DBUS_WATCH_READABLE)
820  revents |= _DBUS_POLLIN;
821  if (condition & DBUS_WATCH_ERROR)
822  revents |= _DBUS_POLLERR;
823  if (condition & DBUS_WATCH_HANGUP)
824  revents |= _DBUS_POLLHUP;
825 
826  fd = dbus_watch_get_socket (watch);
827 
828  if (fd == sitter->error_pipe_from_child)
829  handle_error_pipe (sitter, revents);
830  else if (fd == sitter->socket_to_babysitter)
831  handle_babysitter_socket (sitter, revents);
832 
833  while (LIVE_CHILDREN (sitter) &&
834  babysitter_iteration (sitter, FALSE))
835  ;
836 
837  /* fd.o #32992: if the handle_* methods closed their sockets, they previously
838  * didn't always remove the watches. Check that we don't regress. */
839  _dbus_assert (sitter->socket_to_babysitter != -1 || sitter->sitter_watch == NULL);
840  _dbus_assert (sitter->error_pipe_from_child != -1 || sitter->error_watch == NULL);
841 
842  if (_dbus_babysitter_get_child_exited (sitter) &&
843  sitter->finished_cb != NULL)
844  {
845  sitter->finished_cb (sitter, sitter->finished_data);
846  sitter->finished_cb = NULL;
847  }
848 
849  _dbus_babysitter_unref (sitter);
850  return TRUE;
851 }
852 
854 #define READ_END 0
855 
856 #define WRITE_END 1
857 
858 
859 /* Avoids a danger in re-entrant situations (calling close()
860  * on a file descriptor twice, and another module has
861  * re-opened it since the first close).
862  *
863  * This previously claimed to be relevant for threaded situations, but by
864  * trivial inspection, it is not thread-safe. It doesn't actually
865  * matter, since this module is only used in the -util variant of the
866  * library, which is only used in single-threaded situations.
867  */
868 static int
869 close_and_invalidate (int *fd)
870 {
871  int ret;
872 
873  if (*fd < 0)
874  return -1;
875  else
876  {
877  ret = _dbus_close_socket (*fd, NULL);
878  *fd = -1;
879  }
880 
881  return ret;
882 }
883 
884 static dbus_bool_t
885 make_pipe (int p[2],
886  DBusError *error)
887 {
888  int retval;
889 
890 #ifdef HAVE_PIPE2
891  dbus_bool_t cloexec_done;
892 
893  retval = pipe2 (p, O_CLOEXEC);
894  cloexec_done = retval >= 0;
895 
896  /* Check if kernel seems to be too old to know pipe2(). We assume
897  that if pipe2 is available, O_CLOEXEC is too. */
898  if (retval < 0 && errno == ENOSYS)
899 #endif
900  {
901  retval = pipe(p);
902  }
903 
904  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
905 
906  if (retval < 0)
907  {
908  dbus_set_error (error,
910  "Failed to create pipe for communicating with child process (%s)",
911  _dbus_strerror (errno));
912  return FALSE;
913  }
914 
915 #ifdef HAVE_PIPE2
916  if (!cloexec_done)
917 #endif
918  {
921  }
922 
923  return TRUE;
924 }
925 
926 static void
927 do_write (int fd, const void *buf, size_t count)
928 {
929  size_t bytes_written;
930  int ret;
931 
932  bytes_written = 0;
933 
934  again:
935 
936  ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);
937 
938  if (ret < 0)
939  {
940  if (errno == EINTR)
941  goto again;
942  else
943  {
944  _dbus_warn ("Failed to write data to pipe!\n");
945  exit (1); /* give up, we suck */
946  }
947  }
948  else
949  bytes_written += ret;
950 
951  if (bytes_written < count)
952  goto again;
953 }
954 
955 static void
956 write_err_and_exit (int fd, int msg)
957 {
958  int en = errno;
959 
960  do_write (fd, &msg, sizeof (msg));
961  do_write (fd, &en, sizeof (en));
962 
963  exit (1);
964 }
965 
966 static void
967 write_pid (int fd, pid_t pid)
968 {
969  int msg = CHILD_PID;
970 
971  do_write (fd, &msg, sizeof (msg));
972  do_write (fd, &pid, sizeof (pid));
973 }
974 
975 static void
976 write_status_and_exit (int fd, int status)
977 {
978  int msg = CHILD_EXITED;
979 
980  do_write (fd, &msg, sizeof (msg));
981  do_write (fd, &status, sizeof (status));
982 
983  exit (0);
984 }
985 
986 static void
987 do_exec (int child_err_report_fd,
988  char **argv,
989  char **envp,
990  DBusSpawnChildSetupFunc child_setup,
991  void *user_data)
992 {
993 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
994  int i, max_open;
995 #endif
996 
997  _dbus_verbose_reset ();
998  _dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n",
999  _dbus_getpid ());
1000 
1001  if (child_setup)
1002  (* child_setup) (user_data);
1003 
1004 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
1005  max_open = sysconf (_SC_OPEN_MAX);
1006 
1007  for (i = 3; i < max_open; i++)
1008  {
1009  int retval;
1010 
1011  if (i == child_err_report_fd)
1012  continue;
1013 
1014  retval = fcntl (i, F_GETFD);
1015 
1016  if (retval != -1 && !(retval & FD_CLOEXEC))
1017  _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
1018  }
1019 #endif
1020 
1021  if (envp == NULL)
1022  {
1023  _dbus_assert (environ != NULL);
1024 
1025  envp = environ;
1026  }
1027 
1028  execve (argv[0], argv, envp);
1029 
1030  /* Exec failed */
1031  write_err_and_exit (child_err_report_fd,
1032  CHILD_EXEC_FAILED);
1033 }
1034 
1035 static void
1036 check_babysit_events (pid_t grandchild_pid,
1037  int parent_pipe,
1038  int revents)
1039 {
1040  pid_t ret;
1041  int status;
1042 
1043  do
1044  {
1045  ret = waitpid (grandchild_pid, &status, WNOHANG);
1046  /* The man page says EINTR can't happen with WNOHANG,
1047  * but there are reports of it (maybe only with valgrind?)
1048  */
1049  }
1050  while (ret < 0 && errno == EINTR);
1051 
1052  if (ret == 0)
1053  {
1054  _dbus_verbose ("no child exited\n");
1055 
1056  ; /* no child exited */
1057  }
1058  else if (ret < 0)
1059  {
1060  /* This isn't supposed to happen. */
1061  _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s\n",
1062  _dbus_strerror (errno));
1063  exit (1);
1064  }
1065  else if (ret == grandchild_pid)
1066  {
1067  /* Child exited */
1068  _dbus_verbose ("reaped child pid %ld\n", (long) ret);
1069 
1070  write_status_and_exit (parent_pipe, status);
1071  }
1072  else
1073  {
1074  _dbus_warn ("waitpid() reaped pid %d that we've never heard of\n",
1075  (int) ret);
1076  exit (1);
1077  }
1078 
1079  if (revents & _DBUS_POLLIN)
1080  {
1081  _dbus_verbose ("babysitter got POLLIN from parent pipe\n");
1082  }
1083 
1084  if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
1085  {
1086  /* Parent is gone, so we just exit */
1087  _dbus_verbose ("babysitter got POLLERR or POLLHUP from parent\n");
1088  exit (0);
1089  }
1090 }
1091 
1092 static int babysit_sigchld_pipe = -1;
1093 
1094 static void
1095 babysit_signal_handler (int signo)
1096 {
1097  char b = '\0';
1098  again:
1099  if (write (babysit_sigchld_pipe, &b, 1) <= 0)
1100  if (errno == EINTR)
1101  goto again;
1102 }
1103 
1104 static void
1105 babysit (pid_t grandchild_pid,
1106  int parent_pipe)
1107 {
1108  int sigchld_pipe[2];
1109 
1110  /* We don't exec, so we keep parent state, such as the pid that
1111  * _dbus_verbose() uses. Reset the pid here.
1112  */
1113  _dbus_verbose_reset ();
1114 
1115  /* I thought SIGCHLD would just wake up the poll, but
1116  * that didn't seem to work, so added this pipe.
1117  * Probably the pipe is more likely to work on busted
1118  * operating systems anyhow.
1119  */
1120  if (pipe (sigchld_pipe) < 0)
1121  {
1122  _dbus_warn ("Not enough file descriptors to create pipe in babysitter process\n");
1123  exit (1);
1124  }
1125 
1126  babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
1127 
1128  _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler);
1129 
1130  write_pid (parent_pipe, grandchild_pid);
1131 
1132  check_babysit_events (grandchild_pid, parent_pipe, 0);
1133 
1134  while (TRUE)
1135  {
1136  DBusPollFD pfds[2];
1137 
1138  pfds[0].fd = parent_pipe;
1139  pfds[0].events = _DBUS_POLLIN;
1140  pfds[0].revents = 0;
1141 
1142  pfds[1].fd = sigchld_pipe[READ_END];
1143  pfds[1].events = _DBUS_POLLIN;
1144  pfds[1].revents = 0;
1145 
1146  if (_dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1) < 0 && errno != EINTR)
1147  {
1148  _dbus_warn ("_dbus_poll() error: %s\n", strerror (errno));
1149  exit (1);
1150  }
1151 
1152  if (pfds[0].revents != 0)
1153  {
1154  check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
1155  }
1156  else if (pfds[1].revents & _DBUS_POLLIN)
1157  {
1158  char b;
1159  if (read (sigchld_pipe[READ_END], &b, 1) == -1)
1160  {
1161  /* ignore */
1162  }
1163  /* do waitpid check */
1164  check_babysit_events (grandchild_pid, parent_pipe, 0);
1165  }
1166  }
1167 
1168  exit (1);
1169 }
1170 
1192  const char *log_name,
1193  char **argv,
1194  char **env,
1195  DBusSpawnChildSetupFunc child_setup,
1196  void *user_data,
1197  DBusError *error)
1198 {
1199  DBusBabysitter *sitter;
1200  int child_err_report_pipe[2] = { -1, -1 };
1201  int babysitter_pipe[2] = { -1, -1 };
1202  pid_t pid;
1203 #ifdef HAVE_SYSTEMD
1204  int fd_out = -1;
1205  int fd_err = -1;
1206 #endif
1207 
1208  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1209  _dbus_assert (argv[0] != NULL);
1210 
1211  if (sitter_p != NULL)
1212  *sitter_p = NULL;
1213 
1214  sitter = NULL;
1215 
1216  sitter = _dbus_babysitter_new ();
1217  if (sitter == NULL)
1218  {
1220  return FALSE;
1221  }
1222 
1223  sitter->log_name = _dbus_strdup (log_name);
1224  if (sitter->log_name == NULL && log_name != NULL)
1225  {
1227  goto cleanup_and_fail;
1228  }
1229 
1230  if (sitter->log_name == NULL)
1231  sitter->log_name = _dbus_strdup (argv[0]);
1232 
1233  if (sitter->log_name == NULL)
1234  {
1236  goto cleanup_and_fail;
1237  }
1238 
1239  if (!make_pipe (child_err_report_pipe, error))
1240  goto cleanup_and_fail;
1241 
1242  if (!_dbus_full_duplex_pipe (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error))
1243  goto cleanup_and_fail;
1244 
1245  /* Setting up the babysitter is only useful in the parent,
1246  * but we don't want to run out of memory and fail
1247  * after we've already forked, since then we'd leak
1248  * child processes everywhere.
1249  */
1250  sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END],
1251  DBUS_WATCH_READABLE,
1252  TRUE, handle_watch, sitter, NULL);
1253  if (sitter->error_watch == NULL)
1254  {
1256  goto cleanup_and_fail;
1257  }
1258 
1259  if (!_dbus_watch_list_add_watch (sitter->watches, sitter->error_watch))
1260  {
1261  /* we need to free it early so the destructor won't try to remove it
1262  * without it having been added, which DBusLoop doesn't allow */
1264  _dbus_watch_unref (sitter->error_watch);
1265  sitter->error_watch = NULL;
1266 
1268  goto cleanup_and_fail;
1269  }
1270 
1271  sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0],
1272  DBUS_WATCH_READABLE,
1273  TRUE, handle_watch, sitter, NULL);
1274  if (sitter->sitter_watch == NULL)
1275  {
1277  goto cleanup_and_fail;
1278  }
1279 
1280  if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
1281  {
1282  /* we need to free it early so the destructor won't try to remove it
1283  * without it having been added, which DBusLoop doesn't allow */
1285  _dbus_watch_unref (sitter->sitter_watch);
1286  sitter->sitter_watch = NULL;
1287 
1289  goto cleanup_and_fail;
1290  }
1291 
1292  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1293 
1294 #ifdef HAVE_SYSTEMD
1295  /* This may fail, but it's not critical.
1296  * In particular, if we were compiled with journald support but are now
1297  * running on a non-systemd system, this is going to fail, so we
1298  * have to cope gracefully. */
1299  fd_out = sd_journal_stream_fd (sitter->log_name, LOG_INFO, FALSE);
1300  fd_err = sd_journal_stream_fd (sitter->log_name, LOG_WARNING, FALSE);
1301 #endif
1302 
1303  pid = fork ();
1304 
1305  if (pid < 0)
1306  {
1307  dbus_set_error (error,
1309  "Failed to fork (%s)",
1310  _dbus_strerror (errno));
1311  goto cleanup_and_fail;
1312  }
1313  else if (pid == 0)
1314  {
1315  /* Immediate child, this is the babysitter process. */
1316  int grandchild_pid;
1317 
1318  /* Be sure we crash if the parent exits
1319  * and we write to the err_report_pipe
1320  */
1321  signal (SIGPIPE, SIG_DFL);
1322 
1323  /* Close the parent's end of the pipes. */
1324  close_and_invalidate (&child_err_report_pipe[READ_END]);
1325  close_and_invalidate (&babysitter_pipe[0]);
1326 
1327  /* Create the child that will exec () */
1328  grandchild_pid = fork ();
1329 
1330  if (grandchild_pid < 0)
1331  {
1332  write_err_and_exit (babysitter_pipe[1],
1333  CHILD_FORK_FAILED);
1334  _dbus_assert_not_reached ("Got to code after write_err_and_exit()");
1335  }
1336  else if (grandchild_pid == 0)
1337  {
1338  /* Go back to ignoring SIGPIPE, since it's evil
1339  */
1340  signal (SIGPIPE, SIG_IGN);
1341 
1342  close_and_invalidate (&babysitter_pipe[1]);
1343 #ifdef HAVE_SYSTEMD
1344  /* log to systemd journal if possible */
1345  if (fd_out >= 0)
1346  dup2 (fd_out, STDOUT_FILENO);
1347  if (fd_err >= 0)
1348  dup2 (fd_err, STDERR_FILENO);
1349  close_and_invalidate (&fd_out);
1350  close_and_invalidate (&fd_err);
1351 #endif
1352  do_exec (child_err_report_pipe[WRITE_END],
1353  argv,
1354  env,
1355  child_setup, user_data);
1356  _dbus_assert_not_reached ("Got to code after exec() - should have exited on error");
1357  }
1358  else
1359  {
1360  close_and_invalidate (&child_err_report_pipe[WRITE_END]);
1361 #ifdef HAVE_SYSTEMD
1362  close_and_invalidate (&fd_out);
1363  close_and_invalidate (&fd_err);
1364 #endif
1365  babysit (grandchild_pid, babysitter_pipe[1]);
1366  _dbus_assert_not_reached ("Got to code after babysit()");
1367  }
1368  }
1369  else
1370  {
1371  /* Close the uncared-about ends of the pipes */
1372  close_and_invalidate (&child_err_report_pipe[WRITE_END]);
1373  close_and_invalidate (&babysitter_pipe[1]);
1374 #ifdef HAVE_SYSTEMD
1375  close_and_invalidate (&fd_out);
1376  close_and_invalidate (&fd_err);
1377 #endif
1378 
1379  sitter->socket_to_babysitter = babysitter_pipe[0];
1380  babysitter_pipe[0] = -1;
1381 
1382  sitter->error_pipe_from_child = child_err_report_pipe[READ_END];
1383  child_err_report_pipe[READ_END] = -1;
1384 
1385  sitter->sitter_pid = pid;
1386 
1387  if (sitter_p != NULL)
1388  *sitter_p = sitter;
1389  else
1390  _dbus_babysitter_unref (sitter);
1391 
1392  dbus_free_string_array (env);
1393 
1394  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1395 
1396  return TRUE;
1397  }
1398 
1399  cleanup_and_fail:
1400 
1401  _DBUS_ASSERT_ERROR_IS_SET (error);
1402 
1403  close_and_invalidate (&child_err_report_pipe[READ_END]);
1404  close_and_invalidate (&child_err_report_pipe[WRITE_END]);
1405  close_and_invalidate (&babysitter_pipe[0]);
1406  close_and_invalidate (&babysitter_pipe[1]);
1407 #ifdef HAVE_SYSTEMD
1408  close_and_invalidate (&fd_out);
1409  close_and_invalidate (&fd_err);
1410 #endif
1411 
1412  if (sitter != NULL)
1413  _dbus_babysitter_unref (sitter);
1414 
1415  return FALSE;
1416 }
1417 
1418 void
1419 _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
1420  DBusBabysitterFinishedFunc finished,
1421  void *user_data)
1422 {
1423  sitter->finished_cb = finished;
1424  sitter->finished_data = user_data;
1425 }
1426 
1429 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
1430 
1431 static char *
1432 get_test_exec (const char *exe,
1433  DBusString *scratch_space)
1434 {
1435  const char *dbus_test_exec;
1436 
1437  dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
1438 
1439  if (dbus_test_exec == NULL)
1440  dbus_test_exec = DBUS_TEST_EXEC;
1441 
1442  if (!_dbus_string_init (scratch_space))
1443  return NULL;
1444 
1445  if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
1446  dbus_test_exec, exe, DBUS_EXEEXT))
1447  {
1448  _dbus_string_free (scratch_space);
1449  return NULL;
1450  }
1451 
1452  return _dbus_string_get_data (scratch_space);
1453 }
1454 
1455 static void
1456 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
1457 {
1458  while (LIVE_CHILDREN (sitter))
1459  babysitter_iteration (sitter, TRUE);
1460 }
1461 
1462 static dbus_bool_t
1463 check_spawn_nonexistent (void *data)
1464 {
1465  char *argv[4] = { NULL, NULL, NULL, NULL };
1466  DBusBabysitter *sitter = NULL;
1467  DBusError error = DBUS_ERROR_INIT;
1468 
1469  /*** Test launching nonexistent binary */
1470 
1471  argv[0] = "/this/does/not/exist/32542sdgafgafdg";
1472  if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_nonexistent", argv,
1473  NULL, NULL, NULL,
1474  &error))
1475  {
1476  _dbus_babysitter_block_for_child_exit (sitter);
1477  _dbus_babysitter_set_child_exit_error (sitter, &error);
1478  }
1479 
1480  if (sitter)
1481  _dbus_babysitter_unref (sitter);
1482 
1483  if (!dbus_error_is_set (&error))
1484  {
1485  _dbus_warn ("Did not get an error launching nonexistent executable\n");
1486  return FALSE;
1487  }
1488 
1489  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
1491  {
1492  _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
1493  error.name, error.message);
1494  dbus_error_free (&error);
1495  return FALSE;
1496  }
1497 
1498  dbus_error_free (&error);
1499 
1500  return TRUE;
1501 }
1502 
1503 static dbus_bool_t
1504 check_spawn_segfault (void *data)
1505 {
1506  char *argv[4] = { NULL, NULL, NULL, NULL };
1507  DBusBabysitter *sitter = NULL;
1508  DBusError error = DBUS_ERROR_INIT;
1509  DBusString argv0;
1510 
1511  /*** Test launching segfault binary */
1512 
1513  argv[0] = get_test_exec ("test-segfault", &argv0);
1514 
1515  if (argv[0] == NULL)
1516  {
1517  /* OOM was simulated, never mind */
1518  return TRUE;
1519  }
1520 
1521  if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_segfault", argv,
1522  NULL, NULL, NULL,
1523  &error))
1524  {
1525  _dbus_babysitter_block_for_child_exit (sitter);
1526  _dbus_babysitter_set_child_exit_error (sitter, &error);
1527  }
1528 
1529  _dbus_string_free (&argv0);
1530 
1531  if (sitter)
1532  _dbus_babysitter_unref (sitter);
1533 
1534  if (!dbus_error_is_set (&error))
1535  {
1536  _dbus_warn ("Did not get an error launching segfaulting binary\n");
1537  return FALSE;
1538  }
1539 
1540  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
1542  {
1543  _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
1544  error.name, error.message);
1545  dbus_error_free (&error);
1546  return FALSE;
1547  }
1548 
1549  dbus_error_free (&error);
1550 
1551  return TRUE;
1552 }
1553 
1554 static dbus_bool_t
1555 check_spawn_exit (void *data)
1556 {
1557  char *argv[4] = { NULL, NULL, NULL, NULL };
1558  DBusBabysitter *sitter = NULL;
1559  DBusError error = DBUS_ERROR_INIT;
1560  DBusString argv0;
1561 
1562  /*** Test launching exit failure binary */
1563 
1564  argv[0] = get_test_exec ("test-exit", &argv0);
1565 
1566  if (argv[0] == NULL)
1567  {
1568  /* OOM was simulated, never mind */
1569  return TRUE;
1570  }
1571 
1572  if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_exit", argv,
1573  NULL, NULL, NULL,
1574  &error))
1575  {
1576  _dbus_babysitter_block_for_child_exit (sitter);
1577  _dbus_babysitter_set_child_exit_error (sitter, &error);
1578  }
1579 
1580  _dbus_string_free (&argv0);
1581 
1582  if (sitter)
1583  _dbus_babysitter_unref (sitter);
1584 
1585  if (!dbus_error_is_set (&error))
1586  {
1587  _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
1588  return FALSE;
1589  }
1590 
1591  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
1593  {
1594  _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
1595  error.name, error.message);
1596  dbus_error_free (&error);
1597  return FALSE;
1598  }
1599 
1600  dbus_error_free (&error);
1601 
1602  return TRUE;
1603 }
1604 
1605 static dbus_bool_t
1606 check_spawn_and_kill (void *data)
1607 {
1608  char *argv[4] = { NULL, NULL, NULL, NULL };
1609  DBusBabysitter *sitter = NULL;
1610  DBusError error = DBUS_ERROR_INIT;
1611  DBusString argv0;
1612 
1613  /*** Test launching sleeping binary then killing it */
1614 
1615  argv[0] = get_test_exec ("test-sleep-forever", &argv0);
1616 
1617  if (argv[0] == NULL)
1618  {
1619  /* OOM was simulated, never mind */
1620  return TRUE;
1621  }
1622 
1623  if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv,
1624  NULL, NULL, NULL,
1625  &error))
1626  {
1627  _dbus_babysitter_kill_child (sitter);
1628 
1629  _dbus_babysitter_block_for_child_exit (sitter);
1630 
1631  _dbus_babysitter_set_child_exit_error (sitter, &error);
1632  }
1633 
1634  _dbus_string_free (&argv0);
1635 
1636  if (sitter)
1637  _dbus_babysitter_unref (sitter);
1638 
1639  if (!dbus_error_is_set (&error))
1640  {
1641  _dbus_warn ("Did not get an error after killing spawned binary\n");
1642  return FALSE;
1643  }
1644 
1645  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
1647  {
1648  _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
1649  error.name, error.message);
1650  dbus_error_free (&error);
1651  return FALSE;
1652  }
1653 
1654  dbus_error_free (&error);
1655 
1656  return TRUE;
1657 }
1658 
1660 _dbus_spawn_test (const char *test_data_dir)
1661 {
1662  if (!_dbus_test_oom_handling ("spawn_nonexistent",
1663  check_spawn_nonexistent,
1664  NULL))
1665  return FALSE;
1666 
1667  if (!_dbus_test_oom_handling ("spawn_segfault",
1668  check_spawn_segfault,
1669  NULL))
1670  return FALSE;
1671 
1672  if (!_dbus_test_oom_handling ("spawn_exit",
1673  check_spawn_exit,
1674  NULL))
1675  return FALSE;
1676 
1677  if (!_dbus_test_oom_handling ("spawn_and_kill",
1678  check_spawn_and_kill,
1679  NULL))
1680  return FALSE;
1681 
1682  return TRUE;
1683 }
1684 #endif
dbus_bool_t dbus_error_has_name(const DBusError *error, const char *name)
Checks whether the error is set and has the given name.
Definition: dbus-errors.c:302
const char * message
public error message field
Definition: dbus-errors.h:51
#define DBUS_ERROR_SPAWN_FAILED
While starting a new process, something went wrong.
Implementation of DBusWatch.
Definition: dbus-watch.c:40
#define NULL
A null pointer, defined appropriately for C or C++.
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
Definition: dbus-memory.h:64
#define LIVE_CHILDREN(sitter)
Macro returns TRUE if the babysitter still has live sockets open to the babysitter child or the grand...
Definition: dbus-spawn.c:656
#define _DBUS_POLLHUP
Hung up.
Definition: dbus-sysdeps.h:302
void(* DBusRemoveWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus no longer needs a watch to be monitored by the main loop.
unsigned int have_exec_errnum
True if we have an error code from exec()
Definition: dbus-spawn.c:261
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:701
DBusWatch * error_watch
Error pipe watch.
Definition: dbus-spawn.c:251
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
Definition: dbus-watch.c:232
void _dbus_watch_invalidate(DBusWatch *watch)
Clears the file descriptor from a now-invalid watch object so that no one tries to use it...
Definition: dbus-watch.c:169
#define DBUS_PID_FORMAT
an appropriate printf format for dbus_pid_t
Definition: dbus-sysdeps.h:110
#define DBUS_ERROR_SPAWN_CHILD_EXITED
While starting a new process, the child exited with a status code.
int status
Exit status code.
Definition: dbus-spawn.c:258
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
int socket_to_babysitter
Connection to the babysitter process.
dbus_bool_t _dbus_full_duplex_pipe(int *fd1, int *fd2, dbus_bool_t blocking, DBusError *error)
Creates a full-duplex pipe (as in socketpair()).
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition: dbus-errors.h:62
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...
Definition: dbus-watch.c:376
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...
Definition: dbus-errors.c:211
A portable struct pollfd wrapper.
Definition: dbus-sysdeps.h:310
#define _DBUS_POLLIN
There is data to read.
Definition: dbus-sysdeps.h:294
Read succeeded.
Definition: dbus-spawn.c:62
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
dbus_pid_t _dbus_getpid(void)
Gets our process ID.
short events
Events to poll for.
Definition: dbus-sysdeps.h:313
dbus_bool_t _dbus_babysitter_get_child_exited(DBusBabysitter *sitter)
Checks whether the child has exited, without blocking.
Definition: dbus-spawn.c:687
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:185
dbus_bool_t(* DBusAddWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus needs a new watch to be monitored by the main loop.
DBusWatchList * watches
Watches.
void _dbus_fd_set_close_on_exec(intptr_t fd)
Sets the file descriptor to be close on exec.
#define DBUS_ERROR_SPAWN_CHILD_SIGNALED
While starting a new process, the child exited on a signal.
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:59
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
DBusWatch * sitter_watch
Sitter pipe watch.
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...
Definition: dbus-watch.c:565
dbus_bool_t _dbus_babysitter_get_child_exit_status(DBusBabysitter *sitter, int *status)
Gets the exit status of the child.
Definition: dbus-spawn.c:712
void _dbus_babysitter_kill_child(DBusBabysitter *sitter)
Blocks until the babysitter process gives us the PID of the spawned grandchild, then kills the spawne...
Definition: dbus-spawn.c:665
Babysitter implementation details.
ReadStatus
Enumeration for status of a read()
Definition: dbus-spawn.c:60
int _dbus_poll(DBusPollFD *fds, int n_fds, int timeout_milliseconds)
Wrapper for poll().
dbus_bool_t _dbus_spawn_async_with_babysitter(DBusBabysitter **sitter_p, const char *log_name, char **argv, char **env, DBusSpawnChildSetupFunc child_setup, void *user_data, DBusError *error)
Spawns a new process.
Definition: dbus-spawn.c:1191
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
pid_t sitter_pid
PID Of the babysitter.
Definition: dbus-spawn.c:246
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1096
EOF returned.
Definition: dbus-spawn.c:64
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...
Definition: dbus-spawn.c:794
Object representing an exception.
Definition: dbus-errors.h:48
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:354
pid_t grandchild_pid
PID of the grandchild.
Definition: dbus-spawn.c:247
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
int refcount
Reference count.
int fd
File descriptor.
Definition: dbus-sysdeps.h:312
As in POLLERR (can't watch for this, but can be present in current state passed to dbus_watch_handle(...
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:242
#define TRUE
Expands to "1".
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
As in POLLHUP (can't watch for it, but can be present in current state passed to dbus_watch_handle())...
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
const char * name
public error name field
Definition: dbus-errors.h:50
#define READ_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:854
DBusWatchList implementation details.
Definition: dbus-watch.c:214
void _dbus_babysitter_unref(DBusBabysitter *sitter)
Decrement the reference count on the babysitter object.
Definition: dbus-spawn.c:321
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.
Definition: dbus-watch.c:296
#define DBUS_ERROR_SPAWN_FORK_FAILED
While starting a new process, the fork() call failed.
void _dbus_set_signal_handler(int sig, DBusSignalHandler handler)
Installs a UNIX signal handler.
DBusWatch * _dbus_watch_new(int fd, unsigned int flags, dbus_bool_t enabled, DBusWatchHandler handler, void *data, DBusFreeFunction free_data_function)
Creates a new DBusWatch.
Definition: dbus-watch.c:88
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:749
char * log_name
the name under which to log messages about this process being spawned
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
unsigned int have_fork_errnum
True if we have an error code from fork()
Definition: dbus-spawn.c:260
#define FALSE
Expands to "0".
int error_pipe_from_child
Connection to the process that does the exec()
Definition: dbus-spawn.c:244
void _dbus_watch_unref(DBusWatch *watch)
Decrements the reference count of a DBusWatch object and finalizes the object if the count reaches ze...
Definition: dbus-watch.c:138
void(* DBusWatchToggledFunction)(DBusWatch *watch, void *data)
Called when dbus_watch_get_enabled() may return a different value than it did before.
As in POLLIN.
#define WRITE_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:856
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
Definition: dbus-watch.c:249
char * _dbus_strdup(const char *str)
Duplicates a string.
dbus_bool_t _dbus_close_socket(int fd, DBusError *error)
Closes a socket.
int errnum
Error number.
Definition: dbus-spawn.c:257
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...
Definition: dbus-spawn.c:736
short revents
Events that occurred.
Definition: dbus-sysdeps.h:314
dbus_bool_t dbus_error_is_set(const DBusError *error)
Checks whether an error occurred (the error is set).
Definition: dbus-errors.c:329
Some kind of error.
Definition: dbus-spawn.c:63
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...
Definition: dbus-watch.c:409
#define _DBUS_POLLERR
Error condition.
Definition: dbus-sysdeps.h:300
DBusBabysitter * _dbus_babysitter_ref(DBusBabysitter *sitter)
Increment the reference count on the babysitter object.
Definition: dbus-spawn.c:299