D-Bus  1.12.20
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 #ifdef HAVE_SYSLOG_H
43 #include <syslog.h>
44 #endif
45 #include <systemd/sd-journal.h>
46 #endif
47 
48 #if defined(__APPLE__)
49 # include <crt_externs.h>
50 # define environ (*_NSGetEnviron ())
51 #elif !HAVE_DECL_ENVIRON
52 extern char **environ;
53 #endif
54 
55 #ifdef HAVE_PDPLINUX
56 dbus_bool_t bus_activation_pdplinux_set_proc_label(void* actdata, DBusConnection* connection, pid_t pid);
57 #endif
58 
64 /*
65  * I'm pretty sure this whole spawn file could be made simpler,
66  * if you thought about it a bit.
67  */
68 
72 typedef enum
73 {
78 
79 static ReadStatus
80 read_ints (int fd,
81  int *buf,
82  int n_ints_in_buf,
83  int *n_ints_read,
84  DBusError *error)
85 {
86  size_t bytes = 0;
87  ReadStatus retval;
88 
89  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
90 
91  retval = READ_STATUS_OK;
92 
93  while (TRUE)
94  {
95  ssize_t chunk;
96  size_t to_read;
97 
98  to_read = sizeof (int) * n_ints_in_buf - bytes;
99 
100  if (to_read == 0)
101  break;
102 
103  again:
104 
105  chunk = read (fd,
106  ((char*)buf) + bytes,
107  to_read);
108 
109  if (chunk < 0 && errno == EINTR)
110  goto again;
111 
112  if (chunk < 0)
113  {
114  dbus_set_error (error,
116  "Failed to read from child pipe (%s)",
117  _dbus_strerror (errno));
118 
119  retval = READ_STATUS_ERROR;
120  break;
121  }
122  else if (chunk == 0)
123  {
124  retval = READ_STATUS_EOF;
125  break; /* EOF */
126  }
127  else /* chunk > 0 */
128  bytes += chunk;
129  }
130 
131  *n_ints_read = (int)(bytes / sizeof(int));
132 
133  return retval;
134 }
135 
136 static ReadStatus
137 read_pid (int fd,
138  pid_t *buf,
139  DBusError *error)
140 {
141  size_t bytes = 0;
142  ReadStatus retval;
143 
144  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
145 
146  retval = READ_STATUS_OK;
147 
148  while (TRUE)
149  {
150  ssize_t chunk;
151  size_t to_read;
152 
153  to_read = sizeof (pid_t) - bytes;
154 
155  if (to_read == 0)
156  break;
157 
158  again:
159 
160  chunk = read (fd,
161  ((char*)buf) + bytes,
162  to_read);
163  if (chunk < 0 && errno == EINTR)
164  goto again;
165 
166  if (chunk < 0)
167  {
168  dbus_set_error (error,
170  "Failed to read from child pipe (%s)",
171  _dbus_strerror (errno));
172 
173  retval = READ_STATUS_ERROR;
174  break;
175  }
176  else if (chunk == 0)
177  {
178  retval = READ_STATUS_EOF;
179  break; /* EOF */
180  }
181  else /* chunk > 0 */
182  bytes += chunk;
183  }
184 
185  return retval;
186 }
187 
188 /* The implementation uses an intermediate child between the main process
189  * and the grandchild. The grandchild is our spawned process. The intermediate
190  * child is a babysitter process; it keeps track of when the grandchild
191  * exits/crashes, and reaps the grandchild.
192  *
193  * We automatically reap the babysitter process, killing it if necessary,
194  * when the DBusBabysitter's refcount goes to zero.
195  *
196  * Processes:
197  *
198  * main process
199  * | fork() A
200  * \- babysitter
201  * | fork () B
202  * \- grandchild --> exec --> spawned process
203  *
204  * IPC:
205  * child_err_report_pipe
206  * /-----------<---------<--------------\
207  * | ^
208  * v |
209  * main process babysitter grandchild
210  * ^ ^
211  * v v
212  * \-------<->-------/
213  * babysitter_pipe
214  *
215  * child_err_report_pipe is genuinely a pipe.
216  * The READ_END (also called error_pipe_from_child) is used in the main
217  * process. The WRITE_END (also called child_err_report_fd) is used in
218  * the grandchild process.
219  *
220  * On failure, the grandchild process sends CHILD_EXEC_FAILED + errno.
221  * On success, the pipe just closes (because it's close-on-exec) without
222  * sending any bytes.
223  *
224  * babysitter_pipe is mis-named: it's really a bidirectional socketpair.
225  * The [0] end (also called socket_to_babysitter) is used in the main
226  * process, the [1] end (also called parent_pipe) is used in the babysitter.
227  *
228  * If the fork() labelled B in the diagram above fails, the babysitter sends
229  * CHILD_FORK_FAILED + errno.
230  * On success, the babysitter sends CHILD_PID + the grandchild's pid.
231  * On SIGCHLD, the babysitter sends CHILD_EXITED + the exit status.
232  * The main process doesn't explicitly send anything, but when it exits,
233  * the babysitter gets POLLHUP or POLLERR.
234  */
235 
236 /* Messages from children to parents */
237 enum
238 {
239  CHILD_EXITED, /* This message is followed by the exit status int */
240  CHILD_FORK_FAILED, /* Followed by errno */
241  CHILD_EXEC_FAILED, /* Followed by errno */
242  CHILD_PID /* Followed by pid_t */
243 };
244 
248 struct DBusBabysitter
249 {
250  int refcount;
252  char *log_name;
258  pid_t sitter_pid;
266  DBusBabysitterFinishedFunc finished_cb;
267  void *finished_data;
268 
269  int errnum;
270  int status;
271  unsigned int have_child_status : 1;
272  unsigned int have_fork_errnum : 1;
273  unsigned int have_exec_errnum : 1;
274 };
275 
276 static DBusBabysitter*
277 _dbus_babysitter_new (void)
278 {
279  DBusBabysitter *sitter;
280 
281  sitter = dbus_new0 (DBusBabysitter, 1);
282  if (sitter == NULL)
283  return NULL;
284 
285  sitter->refcount = 1;
286 
287  sitter->socket_to_babysitter.fd = -1;
288  sitter->error_pipe_from_child = -1;
289 
290  sitter->sitter_pid = -1;
291  sitter->grandchild_pid = -1;
292 
293  sitter->watches = _dbus_watch_list_new ();
294  if (sitter->watches == NULL)
295  goto failed;
296 
297  return sitter;
298 
299  failed:
300  _dbus_babysitter_unref (sitter);
301  return NULL;
302 }
303 
312 {
313  _dbus_assert (sitter != NULL);
314  _dbus_assert (sitter->refcount > 0);
315 
316  sitter->refcount += 1;
317 
318  return sitter;
319 }
320 
321 static void close_socket_to_babysitter (DBusBabysitter *sitter);
322 static void close_error_pipe_from_child (DBusBabysitter *sitter);
323 
332 void
334 {
335  _dbus_assert (sitter != NULL);
336  _dbus_assert (sitter->refcount > 0);
337 
338  sitter->refcount -= 1;
339  if (sitter->refcount == 0)
340  {
341  /* If we haven't forked other babysitters
342  * since this babysitter and socket were
343  * created then this close will cause the
344  * babysitter to wake up from poll with
345  * a hangup and then the babysitter will
346  * quit itself.
347  */
348  close_socket_to_babysitter (sitter);
349 
350  close_error_pipe_from_child (sitter);
351 
352  if (sitter->sitter_pid > 0)
353  {
354  int status;
355  int ret;
356 
357  /* It's possible the babysitter died on its own above
358  * from the close, or was killed randomly
359  * by some other process, so first try to reap it
360  */
361  ret = waitpid (sitter->sitter_pid, &status, WNOHANG);
362 
363  /* If we couldn't reap the child then kill it, and
364  * try again
365  */
366  if (ret == 0)
367  kill (sitter->sitter_pid, SIGKILL);
368 
369  if (ret == 0)
370  {
371  do
372  {
373  ret = waitpid (sitter->sitter_pid, &status, 0);
374  }
375  while (_DBUS_UNLIKELY (ret < 0 && errno == EINTR));
376  }
377 
378  if (ret < 0)
379  {
380  if (errno == ECHILD)
381  _dbus_warn ("Babysitter process not available to be reaped; should not happen");
382  else
383  _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s",
384  errno, _dbus_strerror (errno));
385  }
386  else
387  {
388  _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n",
389  (long) ret, (long) sitter->sitter_pid);
390 
391  if (WIFEXITED (sitter->status))
392  _dbus_verbose ("Babysitter exited with status %d\n",
393  WEXITSTATUS (sitter->status));
394  else if (WIFSIGNALED (sitter->status))
395  _dbus_verbose ("Babysitter received signal %d\n",
396  WTERMSIG (sitter->status));
397  else
398  _dbus_verbose ("Babysitter exited abnormally\n");
399  }
400 
401  sitter->sitter_pid = -1;
402  }
403 
404  if (sitter->watches)
405  _dbus_watch_list_free (sitter->watches);
406 
407  dbus_free (sitter->log_name);
408 
409  dbus_free (sitter);
410  }
411 }
412 
413 static ReadStatus
414 read_data (DBusBabysitter *sitter,
415  int fd)
416 {
417  int what;
418  int got;
419  DBusError error = DBUS_ERROR_INIT;
420  ReadStatus r;
421 
422  r = read_ints (fd, &what, 1, &got, &error);
423 
424  switch (r)
425  {
426  case READ_STATUS_ERROR:
427  _dbus_warn ("Failed to read data from fd %d: %s", fd, error.message);
428  dbus_error_free (&error);
429  return r;
430 
431  case READ_STATUS_EOF:
432  return r;
433 
434  case READ_STATUS_OK:
435  break;
436 
437  default:
438  _dbus_assert_not_reached ("invalid ReadStatus");
439  break;
440  }
441 
442  if (got == 1)
443  {
444  switch (what)
445  {
446  case CHILD_EXITED:
447  case CHILD_FORK_FAILED:
448  case CHILD_EXEC_FAILED:
449  {
450  int arg;
451 
452  r = read_ints (fd, &arg, 1, &got, &error);
453 
454  switch (r)
455  {
456  case READ_STATUS_ERROR:
457  _dbus_warn ("Failed to read arg from fd %d: %s", fd, error.message);
458  dbus_error_free (&error);
459  return r;
460  case READ_STATUS_EOF:
461  return r;
462  case READ_STATUS_OK:
463  break;
464  default:
465  _dbus_assert_not_reached ("invalid ReadStatus");
466  break;
467  }
468 
469  if (got == 1)
470  {
471  if (what == CHILD_EXITED)
472  {
473  /* Do not reset sitter->errnum to 0 here. We get here if
474  * the babysitter reports that the grandchild process has
475  * exited, and there are two ways that can happen:
476  *
477  * 1. grandchild successfully exec()s the desired process,
478  * but then the desired process exits or is terminated
479  * by a signal. The babysitter observes this and reports
480  * CHILD_EXITED.
481  *
482  * 2. grandchild fails to exec() the desired process,
483  * attempts to report the exec() failure (which
484  * we will receive as CHILD_EXEC_FAILED), and then
485  * exits itself (which will prompt the babysitter to
486  * send CHILD_EXITED). We want the CHILD_EXEC_FAILED
487  * to take precedence (and have its errno logged),
488  * which _dbus_babysitter_set_child_exit_error() does.
489  */
490  sitter->have_child_status = TRUE;
491  sitter->status = arg;
492  _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
493  WIFEXITED (sitter->status), WIFSIGNALED (sitter->status),
494  WEXITSTATUS (sitter->status), WTERMSIG (sitter->status));
495  }
496  else if (what == CHILD_FORK_FAILED)
497  {
498  sitter->have_fork_errnum = TRUE;
499  sitter->errnum = arg;
500  _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum);
501  }
502  else if (what == CHILD_EXEC_FAILED)
503  {
504  sitter->have_exec_errnum = TRUE;
505  sitter->errnum = arg;
506  _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum);
507  }
508  }
509  }
510  break;
511  case CHILD_PID:
512  {
513  pid_t pid = -1;
514 
515  r = read_pid (fd, &pid, &error);
516 
517  switch (r)
518  {
519  case READ_STATUS_ERROR:
520  _dbus_warn ("Failed to read PID from fd %d: %s", fd, error.message);
521  dbus_error_free (&error);
522  return r;
523  case READ_STATUS_EOF:
524  return r;
525  case READ_STATUS_OK:
526  break;
527  default:
528  _dbus_assert_not_reached ("invalid ReadStatus");
529  break;
530  }
531 
532  sitter->grandchild_pid = pid;
533 
534  _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid);
535  }
536  break;
537  default:
538  _dbus_warn ("Unknown message received from babysitter process");
539  break;
540  }
541  }
542 
543  return r;
544 }
545 
546 static void
547 close_socket_to_babysitter (DBusBabysitter *sitter)
548 {
549  _dbus_verbose ("Closing babysitter\n");
550 
551  if (sitter->sitter_watch != NULL)
552  {
553  _dbus_assert (sitter->watches != NULL);
557  sitter->sitter_watch = NULL;
558  }
559 
560  if (sitter->socket_to_babysitter.fd >= 0)
561  {
563  sitter->socket_to_babysitter.fd = -1;
564  }
565 }
566 
567 static void
568 close_error_pipe_from_child (DBusBabysitter *sitter)
569 {
570  _dbus_verbose ("Closing child error\n");
571 
572  if (sitter->error_watch != NULL)
573  {
574  _dbus_assert (sitter->watches != NULL);
577  _dbus_watch_unref (sitter->error_watch);
578  sitter->error_watch = NULL;
579  }
580 
581  if (sitter->error_pipe_from_child >= 0)
582  {
584  sitter->error_pipe_from_child = -1;
585  }
586 }
587 
588 static void
589 handle_babysitter_socket (DBusBabysitter *sitter,
590  int revents)
591 {
592  /* Even if we have POLLHUP, we want to keep reading
593  * data until POLLIN goes away; so this function only
594  * looks at HUP/ERR if no IN is set.
595  */
596  if (revents & _DBUS_POLLIN)
597  {
598  _dbus_verbose ("Reading data from babysitter\n");
599  if (read_data (sitter, sitter->socket_to_babysitter.fd) != READ_STATUS_OK)
600  close_socket_to_babysitter (sitter);
601  }
602  else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
603  {
604  close_socket_to_babysitter (sitter);
605  }
606 }
607 
608 static void
609 handle_error_pipe (DBusBabysitter *sitter,
610  int revents)
611 {
612  if (revents & _DBUS_POLLIN)
613  {
614  _dbus_verbose ("Reading data from child error\n");
615  if (read_data (sitter, sitter->error_pipe_from_child) != READ_STATUS_OK)
616  close_error_pipe_from_child (sitter);
617  }
618  else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
619  {
620  close_error_pipe_from_child (sitter);
621  }
622 }
623 
624 /* returns whether there were any poll events handled */
625 static dbus_bool_t
626 babysitter_iteration (DBusBabysitter *sitter,
627  dbus_bool_t block)
628 {
629  DBusPollFD fds[2];
630  int i;
631  dbus_bool_t descriptors_ready;
632 
633  descriptors_ready = FALSE;
634 
635  i = 0;
636 
637  if (sitter->error_pipe_from_child >= 0)
638  {
639  fds[i].fd = sitter->error_pipe_from_child;
640  fds[i].events = _DBUS_POLLIN;
641  fds[i].revents = 0;
642  ++i;
643  }
644 
645  if (sitter->socket_to_babysitter.fd >= 0)
646  {
647  fds[i].fd = sitter->socket_to_babysitter.fd;
648  fds[i].events = _DBUS_POLLIN;
649  fds[i].revents = 0;
650  ++i;
651  }
652 
653  if (i > 0)
654  {
655  int ret;
656 
657  do
658  {
659  ret = _dbus_poll (fds, i, 0);
660  }
661  while (ret < 0 && errno == EINTR);
662 
663  if (ret == 0 && block)
664  {
665  do
666  {
667  ret = _dbus_poll (fds, i, -1);
668  }
669  while (ret < 0 && errno == EINTR);
670  }
671 
672  if (ret > 0)
673  {
674  descriptors_ready = TRUE;
675 
676  while (i > 0)
677  {
678  --i;
679  if (fds[i].fd == sitter->error_pipe_from_child)
680  handle_error_pipe (sitter, fds[i].revents);
681  else if (fds[i].fd == sitter->socket_to_babysitter.fd)
682  handle_babysitter_socket (sitter, fds[i].revents);
683  }
684  }
685  }
686 
687  return descriptors_ready;
688 }
689 
694 #define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter.fd >= 0 || (sitter)->error_pipe_from_child >= 0)
695 
702 void
704 {
705  /* be sure we have the PID of the child */
706  while (LIVE_CHILDREN (sitter) &&
707  sitter->grandchild_pid == -1)
708  babysitter_iteration (sitter, TRUE);
709 
710  _dbus_verbose ("Got child PID %ld for killing\n",
711  (long) sitter->grandchild_pid);
712 
713  if (sitter->grandchild_pid == -1)
714  return; /* child is already dead, or we're so hosed we'll never recover */
715 
716  kill (sitter->grandchild_pid, SIGKILL);
717 }
718 
726 {
727 
728  /* Be sure we're up-to-date */
729  while (LIVE_CHILDREN (sitter) &&
730  babysitter_iteration (sitter, FALSE))
731  ;
732 
733  /* We will have exited the babysitter when the child has exited */
734  return sitter->socket_to_babysitter.fd < 0;
735 }
736 
751  int *status)
752 {
753  if (!_dbus_babysitter_get_child_exited (sitter))
754  _dbus_assert_not_reached ("Child has not exited");
755 
756  if (!sitter->have_child_status ||
757  !(WIFEXITED (sitter->status)))
758  return FALSE;
759 
760  *status = WEXITSTATUS (sitter->status);
761  return TRUE;
762 }
763 
773 void
775  DBusError *error)
776 {
777  if (!_dbus_babysitter_get_child_exited (sitter))
778  return;
779 
780  /* Note that if exec fails, we will also get a child status
781  * from the babysitter saying the child exited,
782  * so we need to give priority to the exec error
783  */
784  if (sitter->have_exec_errnum)
785  {
787  "Failed to execute program %s: %s",
788  sitter->log_name, _dbus_strerror (sitter->errnum));
789  }
790  else if (sitter->have_fork_errnum)
791  {
793  "Failed to fork a new process %s: %s",
794  sitter->log_name, _dbus_strerror (sitter->errnum));
795  }
796  else if (sitter->have_child_status)
797  {
798  if (WIFEXITED (sitter->status))
800  "Process %s exited with status %d",
801  sitter->log_name, WEXITSTATUS (sitter->status));
802  else if (WIFSIGNALED (sitter->status))
804  "Process %s received signal %d",
805  sitter->log_name, WTERMSIG (sitter->status));
806  else
808  "Process %s exited abnormally",
809  sitter->log_name);
810  }
811  else
812  {
814  "Process %s exited, reason unknown",
815  sitter->log_name);
816  }
817 }
818 
833  DBusAddWatchFunction add_function,
834  DBusRemoveWatchFunction remove_function,
835  DBusWatchToggledFunction toggled_function,
836  void *data,
837  DBusFreeFunction free_data_function)
838 {
839  return _dbus_watch_list_set_functions (sitter->watches,
840  add_function,
841  remove_function,
842  toggled_function,
843  data,
844  free_data_function);
845 }
846 
847 static dbus_bool_t
848 handle_watch (DBusWatch *watch,
849  unsigned int condition,
850  void *data)
851 {
852  DBusBabysitter *sitter = _dbus_babysitter_ref (data);
853  int revents;
854  int fd;
855 
856  revents = 0;
857  if (condition & DBUS_WATCH_READABLE)
858  revents |= _DBUS_POLLIN;
859  if (condition & DBUS_WATCH_ERROR)
860  revents |= _DBUS_POLLERR;
861  if (condition & DBUS_WATCH_HANGUP)
862  revents |= _DBUS_POLLHUP;
863 
864  fd = dbus_watch_get_socket (watch);
865 
866  if (fd == sitter->error_pipe_from_child)
867  handle_error_pipe (sitter, revents);
868  else if (fd == sitter->socket_to_babysitter.fd)
869  handle_babysitter_socket (sitter, revents);
870 
871  while (LIVE_CHILDREN (sitter) &&
872  babysitter_iteration (sitter, FALSE))
873  ;
874 
875  /* fd.o #32992: if the handle_* methods closed their sockets, they previously
876  * didn't always remove the watches. Check that we don't regress. */
877  _dbus_assert (sitter->socket_to_babysitter.fd != -1 || sitter->sitter_watch == NULL);
878  _dbus_assert (sitter->error_pipe_from_child != -1 || sitter->error_watch == NULL);
879 
880  if (_dbus_babysitter_get_child_exited (sitter) &&
881  sitter->finished_cb != NULL)
882  {
883  sitter->finished_cb (sitter, sitter->finished_data);
884  sitter->finished_cb = NULL;
885  }
886 
887  _dbus_babysitter_unref (sitter);
888  return TRUE;
889 }
890 
892 #define READ_END 0
893 
894 #define WRITE_END 1
895 
896 
897 /* Avoids a danger in re-entrant situations (calling close()
898  * on a file descriptor twice, and another module has
899  * re-opened it since the first close).
900  *
901  * This previously claimed to be relevant for threaded situations, but by
902  * trivial inspection, it is not thread-safe. It doesn't actually
903  * matter, since this module is only used in the -util variant of the
904  * library, which is only used in single-threaded situations.
905  */
906 static int
907 close_and_invalidate (int *fd)
908 {
909  int ret;
910 
911  if (*fd < 0)
912  return -1;
913  else
914  {
915  ret = _dbus_close (*fd, NULL);
916  *fd = -1;
917  }
918 
919  return ret;
920 }
921 
922 static dbus_bool_t
923 make_pipe (int p[2],
924  DBusError *error)
925 {
926  int retval;
927 
928 #ifdef HAVE_PIPE2
929  dbus_bool_t cloexec_done;
930 
931  retval = pipe2 (p, O_CLOEXEC);
932  cloexec_done = retval >= 0;
933 
934  /* Check if kernel seems to be too old to know pipe2(). We assume
935  that if pipe2 is available, O_CLOEXEC is too. */
936  if (retval < 0 && errno == ENOSYS)
937 #endif
938  {
939  retval = pipe(p);
940  }
941 
942  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
943 
944  if (retval < 0)
945  {
946  dbus_set_error (error,
948  "Failed to create pipe for communicating with child process (%s)",
949  _dbus_strerror (errno));
950  return FALSE;
951  }
952 
953 #ifdef HAVE_PIPE2
954  if (!cloexec_done)
955 #endif
956  {
959  }
960 
961  return TRUE;
962 }
963 
964 static void
965 do_write (int fd, const void *buf, size_t count)
966 {
967  size_t bytes_written;
968  int ret;
969 
970  bytes_written = 0;
971 
972  again:
973 
974  ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);
975 
976  if (ret < 0)
977  {
978  if (errno == EINTR)
979  goto again;
980  else
981  {
982  _dbus_warn ("Failed to write data to pipe!");
983  exit (1); /* give up, we suck */
984  }
985  }
986  else
987  bytes_written += ret;
988 
989  if (bytes_written < count)
990  goto again;
991 }
992 
993 static void write_err_and_exit (int fd, int msg) _DBUS_GNUC_NORETURN;
994 
995 static void
996 write_err_and_exit (int fd, int msg)
997 {
998  int en = errno;
999 
1000  do_write (fd, &msg, sizeof (msg));
1001  do_write (fd, &en, sizeof (en));
1002 
1003  exit (1);
1004 }
1005 
1006 static void
1007 write_pid (int fd, pid_t pid)
1008 {
1009  int msg = CHILD_PID;
1010 
1011  do_write (fd, &msg, sizeof (msg));
1012  do_write (fd, &pid, sizeof (pid));
1013 }
1014 
1015 static void write_status_and_exit (int fd, int status) _DBUS_GNUC_NORETURN;
1016 
1017 static void
1018 write_status_and_exit (int fd, int status)
1019 {
1020  int msg = CHILD_EXITED;
1021 
1022  do_write (fd, &msg, sizeof (msg));
1023  do_write (fd, &status, sizeof (status));
1024 
1025  exit (0);
1026 }
1027 
1028 static void do_exec (int child_err_report_fd,
1029  char * const *argv,
1030  char * const *envp,
1031  DBusSpawnChildSetupFunc child_setup,
1032  void *user_data) _DBUS_GNUC_NORETURN;
1033 
1034 static void
1035 do_exec (int child_err_report_fd,
1036  char * const *argv,
1037  char * const *envp,
1038  DBusSpawnChildSetupFunc child_setup,
1039  void *user_data)
1040 {
1041 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
1042  int i, max_open;
1043 #endif
1044 
1045  _dbus_verbose_reset ();
1046  _dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n",
1047  _dbus_getpid ());
1048 
1049  if (child_setup)
1050  (* child_setup) (user_data);
1051 
1052 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
1053  max_open = sysconf (_SC_OPEN_MAX);
1054 
1055  for (i = 3; i < max_open; i++)
1056  {
1057  int retval;
1058 
1059  if (i == child_err_report_fd)
1060  continue;
1061 
1062  retval = fcntl (i, F_GETFD);
1063 
1064  if (retval != -1 && !(retval & FD_CLOEXEC))
1065  _dbus_warn ("Fd %d did not have the close-on-exec flag set!", i);
1066  }
1067 #endif
1068 
1069  if (envp == NULL)
1070  {
1071  _dbus_assert (environ != NULL);
1072 
1073  envp = environ;
1074  }
1075 
1076 #ifdef HAVE_PDPLINUX
1077  {
1078  PDPL_T* pdpl=NULL;
1079  pdpl=pdp_get_current();
1080 
1081  if (pdpl){
1082  _dbus_pdplinux_show_text_label_info2("New process (i.e. current) label",pdpl);
1083  _dbus_verbose("New process UID=%d\n", getuid());
1084  pdpl_put(pdpl);
1085  }
1086 
1087  _dbus_verbose("New process name %s\n", argv[0]);
1088  _dbus_verbose("parameter 1 for execve (%s)\n", argv[1]);
1089  }
1090 #endif
1091 
1092  execve (argv[0], argv, envp);
1093 
1094  /* Exec failed */
1095 #if defined HAVE_PDPLINUX && defined DBUS_ENABLE_VERBOSE_MODE
1096  _dbus_verbose("Exec failed\n");
1097 #endif
1098 
1099  write_err_and_exit (child_err_report_fd,
1100  CHILD_EXEC_FAILED);
1101 }
1102 
1103 static void
1104 check_babysit_events (pid_t grandchild_pid,
1105  int parent_pipe,
1106  int revents)
1107 {
1108  pid_t ret;
1109  int status;
1110 
1111  do
1112  {
1113  ret = waitpid (grandchild_pid, &status, WNOHANG);
1114  /* The man page says EINTR can't happen with WNOHANG,
1115  * but there are reports of it (maybe only with valgrind?)
1116  */
1117  }
1118  while (ret < 0 && errno == EINTR);
1119 
1120  if (ret == 0)
1121  {
1122  _dbus_verbose ("no child exited\n");
1123 
1124  ; /* no child exited */
1125  }
1126  else if (ret < 0)
1127  {
1128  /* This isn't supposed to happen. */
1129  _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s",
1130  _dbus_strerror (errno));
1131  exit (1);
1132  }
1133  else if (ret == grandchild_pid)
1134  {
1135  /* Child exited */
1136  _dbus_verbose ("reaped child pid %ld\n", (long) ret);
1137 
1138  write_status_and_exit (parent_pipe, status);
1139  }
1140  else
1141  {
1142  _dbus_warn ("waitpid() reaped pid %d that we've never heard of",
1143  (int) ret);
1144  exit (1);
1145  }
1146 
1147  if (revents & _DBUS_POLLIN)
1148  {
1149  _dbus_verbose ("babysitter got POLLIN from parent pipe\n");
1150  }
1151 
1152  if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
1153  {
1154  /* Parent is gone, so we just exit */
1155  _dbus_verbose ("babysitter got POLLERR or POLLHUP from parent\n");
1156  exit (0);
1157  }
1158 }
1159 
1160 static int babysit_sigchld_pipe = -1;
1161 
1162 static void
1163 babysit_signal_handler (int signo)
1164 {
1165  /* Signal handlers that might set errno must save and restore the errno
1166  * that the interrupted function might have been relying on. */
1167  int saved_errno = errno;
1168  char b = '\0';
1169 
1170  again:
1171  if (write (babysit_sigchld_pipe, &b, 1) <= 0)
1172  if (errno == EINTR)
1173  goto again;
1174 
1175  errno = saved_errno;
1176 }
1177 
1178 static void babysit (pid_t grandchild_pid,
1179  int parent_pipe) _DBUS_GNUC_NORETURN;
1180 
1181 static void
1182 babysit (pid_t grandchild_pid,
1183  int parent_pipe)
1184 {
1185  int sigchld_pipe[2];
1186 
1187  /* We don't exec, so we keep parent state, such as the pid that
1188  * _dbus_verbose() uses. Reset the pid here.
1189  */
1190  _dbus_verbose_reset ();
1191 
1192  /* I thought SIGCHLD would just wake up the poll, but
1193  * that didn't seem to work, so added this pipe.
1194  * Probably the pipe is more likely to work on busted
1195  * operating systems anyhow.
1196  */
1197  if (pipe (sigchld_pipe) < 0)
1198  {
1199  _dbus_warn ("Not enough file descriptors to create pipe in babysitter process");
1200  exit (1);
1201  }
1202 
1203  babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
1204 
1205  _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler);
1206 
1207  write_pid (parent_pipe, grandchild_pid);
1208 
1209  check_babysit_events (grandchild_pid, parent_pipe, 0);
1210 
1211  while (TRUE)
1212  {
1213  DBusPollFD pfds[2];
1214 
1215  pfds[0].fd = parent_pipe;
1216  pfds[0].events = _DBUS_POLLIN;
1217  pfds[0].revents = 0;
1218 
1219  pfds[1].fd = sigchld_pipe[READ_END];
1220  pfds[1].events = _DBUS_POLLIN;
1221  pfds[1].revents = 0;
1222 
1223  if (_dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1) < 0 && errno != EINTR)
1224  {
1225  _dbus_warn ("_dbus_poll() error: %s", strerror (errno));
1226  exit (1);
1227  }
1228 
1229  if (pfds[0].revents != 0)
1230  {
1231  check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
1232  }
1233  else if (pfds[1].revents & _DBUS_POLLIN)
1234  {
1235  char b;
1236  if (read (sigchld_pipe[READ_END], &b, 1) == -1)
1237  {
1238  /* ignore */
1239  }
1240  /* do waitpid check */
1241  check_babysit_events (grandchild_pid, parent_pipe, 0);
1242  }
1243  }
1244 
1245  exit (1);
1246 }
1247 
1274  const char *log_name,
1275  char * const *argv,
1276  char **env,
1277  DBusSpawnFlags flags,
1278  DBusSpawnChildSetupFunc child_setup,
1279  void *user_data,
1280  DBusError *error
1281 #ifdef HAVE_PDPLINUX
1282  ,DBusConnection* connection)
1283 #else
1284  )
1285 #endif
1286 {
1287  DBusBabysitter *sitter;
1288  int child_err_report_pipe[2] = { -1, -1 };
1289  DBusSocket babysitter_pipe[2] = { DBUS_SOCKET_INIT, DBUS_SOCKET_INIT };
1290  pid_t pid;
1291 #ifdef HAVE_SYSTEMD
1292  int fd_out = -1;
1293  int fd_err = -1;
1294 #endif
1295 
1296  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1297  _dbus_assert (argv[0] != NULL);
1298 
1299  if (sitter_p != NULL)
1300  *sitter_p = NULL;
1301 
1302  sitter = NULL;
1303 
1304  sitter = _dbus_babysitter_new ();
1305  if (sitter == NULL)
1306  {
1308  return FALSE;
1309  }
1310 
1311  sitter->log_name = _dbus_strdup (log_name);
1312  if (sitter->log_name == NULL && log_name != NULL)
1313  {
1315  goto cleanup_and_fail;
1316  }
1317 
1318  if (sitter->log_name == NULL)
1319  sitter->log_name = _dbus_strdup (argv[0]);
1320 
1321  if (sitter->log_name == NULL)
1322  {
1324  goto cleanup_and_fail;
1325  }
1326 
1327  if (!make_pipe (child_err_report_pipe, error))
1328  goto cleanup_and_fail;
1329 
1330  if (!_dbus_socketpair (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error))
1331  goto cleanup_and_fail;
1332 
1333  /* Setting up the babysitter is only useful in the parent,
1334  * but we don't want to run out of memory and fail
1335  * after we've already forked, since then we'd leak
1336  * child processes everywhere.
1337  */
1338  sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END],
1340  TRUE, handle_watch, sitter, NULL);
1341  if (sitter->error_watch == NULL)
1342  {
1344  goto cleanup_and_fail;
1345  }
1346 
1347  if (!_dbus_watch_list_add_watch (sitter->watches, sitter->error_watch))
1348  {
1349  /* we need to free it early so the destructor won't try to remove it
1350  * without it having been added, which DBusLoop doesn't allow */
1352  _dbus_watch_unref (sitter->error_watch);
1353  sitter->error_watch = NULL;
1354 
1356  goto cleanup_and_fail;
1357  }
1358 
1359  sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0].fd,
1361  TRUE, handle_watch, sitter, NULL);
1362  if (sitter->sitter_watch == NULL)
1363  {
1365  goto cleanup_and_fail;
1366  }
1367 
1368  if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
1369  {
1370  /* we need to free it early so the destructor won't try to remove it
1371  * without it having been added, which DBusLoop doesn't allow */
1373  _dbus_watch_unref (sitter->sitter_watch);
1374  sitter->sitter_watch = NULL;
1375 
1377  goto cleanup_and_fail;
1378  }
1379 
1380  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1381 
1382 #ifdef HAVE_SYSTEMD
1383  if (flags & DBUS_SPAWN_REDIRECT_OUTPUT)
1384  {
1385  /* This may fail, but it's not critical.
1386  * In particular, if we were compiled with journald support but are now
1387  * running on a non-systemd system, this is going to fail, so we
1388  * have to cope gracefully. */
1389  fd_out = sd_journal_stream_fd (sitter->log_name, LOG_INFO, FALSE);
1390  fd_err = sd_journal_stream_fd (sitter->log_name, LOG_WARNING, FALSE);
1391  }
1392 #endif
1393 
1394  pid = fork ();
1395 
1396  if (pid < 0)
1397  {
1398  dbus_set_error (error,
1400  "Failed to fork (%s)",
1401  _dbus_strerror (errno));
1402  goto cleanup_and_fail;
1403  }
1404  else if (pid == 0)
1405  {
1406  /* Immediate child, this is the babysitter process. */
1407  int grandchild_pid;
1408 
1409  /* Be sure we crash if the parent exits
1410  * and we write to the err_report_pipe
1411  */
1412  signal (SIGPIPE, SIG_DFL);
1413 
1414  /* Close the parent's end of the pipes. */
1415  close_and_invalidate (&child_err_report_pipe[READ_END]);
1416  close_and_invalidate (&babysitter_pipe[0].fd);
1417 
1418  /* Create the child that will exec () */
1419  grandchild_pid = fork ();
1420 
1421  if (grandchild_pid < 0)
1422  {
1423  write_err_and_exit (babysitter_pipe[1].fd,
1424  CHILD_FORK_FAILED);
1425  _dbus_assert_not_reached ("Got to code after write_err_and_exit()");
1426  }
1427  else if (grandchild_pid == 0)
1428  {
1429 #ifdef __linux__
1430  int fd = -1;
1431 
1432 #ifdef O_CLOEXEC
1433  fd = open ("/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
1434 #endif
1435 
1436  if (fd < 0)
1437  {
1438  fd = open ("/proc/self/oom_score_adj", O_WRONLY);
1440  }
1441 
1442  if (fd >= 0)
1443  {
1444  if (write (fd, "0", sizeof (char)) < 0)
1445  _dbus_warn ("writing oom_score_adj error: %s", strerror (errno));
1446  _dbus_close (fd, NULL);
1447  }
1448 #endif
1449  /* Go back to ignoring SIGPIPE, since it's evil
1450  */
1451  signal (SIGPIPE, SIG_IGN);
1452 
1453  close_and_invalidate (&babysitter_pipe[1].fd);
1454 #ifdef HAVE_SYSTEMD
1455  /* log to systemd journal if possible */
1456  if (fd_out >= 0)
1457  dup2 (fd_out, STDOUT_FILENO);
1458  if (fd_err >= 0)
1459  dup2 (fd_err, STDERR_FILENO);
1460  close_and_invalidate (&fd_out);
1461  close_and_invalidate (&fd_err);
1462 #endif
1463  do_exec (child_err_report_pipe[WRITE_END],
1464  argv,
1465  env,
1466  child_setup, user_data);
1467  _dbus_assert_not_reached ("Got to code after exec() - should have exited on error");
1468  }
1469  else
1470  {
1471 
1472 #ifdef HAVE_PDPLINUX
1473  _dbus_verbose("We are on babysitter !\n");
1474  if(bus_activation_pdplinux_set_proc_label(user_data,connection,(pid_t)grandchild_pid))
1475  _dbus_verbose("Set process label success\n");
1476  else
1477  _dbus_verbose("Set process label failed or skipped\n");
1478 #endif
1479 
1480  close_and_invalidate (&child_err_report_pipe[WRITE_END]);
1481 #ifdef HAVE_SYSTEMD
1482  close_and_invalidate (&fd_out);
1483  close_and_invalidate (&fd_err);
1484 #endif
1485  babysit (grandchild_pid, babysitter_pipe[1].fd);
1486  _dbus_assert_not_reached ("Got to code after babysit()");
1487  }
1488  }
1489  else
1490  {
1491  /* Close the uncared-about ends of the pipes */
1492  close_and_invalidate (&child_err_report_pipe[WRITE_END]);
1493  close_and_invalidate (&babysitter_pipe[1].fd);
1494 #ifdef HAVE_SYSTEMD
1495  close_and_invalidate (&fd_out);
1496  close_and_invalidate (&fd_err);
1497 #endif
1498 
1499  sitter->socket_to_babysitter = babysitter_pipe[0];
1500  babysitter_pipe[0].fd = -1;
1501 
1502  sitter->error_pipe_from_child = child_err_report_pipe[READ_END];
1503  child_err_report_pipe[READ_END] = -1;
1504 
1505  sitter->sitter_pid = pid;
1506 
1507  if (sitter_p != NULL)
1508  *sitter_p = sitter;
1509  else
1510  _dbus_babysitter_unref (sitter);
1511 
1512  dbus_free_string_array (env);
1513 
1514  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1515 
1516  return TRUE;
1517  }
1518 
1519  cleanup_and_fail:
1520 
1521  _DBUS_ASSERT_ERROR_IS_SET (error);
1522 
1523  close_and_invalidate (&child_err_report_pipe[READ_END]);
1524  close_and_invalidate (&child_err_report_pipe[WRITE_END]);
1525  close_and_invalidate (&babysitter_pipe[0].fd);
1526  close_and_invalidate (&babysitter_pipe[1].fd);
1527 #ifdef HAVE_SYSTEMD
1528  close_and_invalidate (&fd_out);
1529  close_and_invalidate (&fd_err);
1530 #endif
1531 
1532  if (sitter != NULL)
1533  _dbus_babysitter_unref (sitter);
1534 
1535  return FALSE;
1536 }
1537 
1538 void
1539 _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
1540  DBusBabysitterFinishedFunc finished,
1541  void *user_data)
1542 {
1543  sitter->finished_cb = finished;
1544  sitter->finished_data = user_data;
1545 }
1546 
1549 void
1550 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
1551 {
1552  while (LIVE_CHILDREN (sitter))
1553  babysitter_iteration (sitter, TRUE);
1554 }
1555 
1556 // ********************************PDP********************************
1557 // Use option to set label from connection to activated process (conn -- LBL --> process)
1558 //#define PDP_FORCE_SET_LABEL_AT_ACTIVATION_TIME
1559 
1560 #ifdef HAVE_PDPLINUX
1561 dbus_bool_t bus_activation_pdplinux_set_proc_label(void* actdata, DBusConnection* connection, pid_t pid){
1562  // don't use functions from bus because linker: unresolved external on libdbus-1 occured!
1563 
1564  dbus_bool_t res=FALSE;
1565  PDPL_T* pdpl=NULL;
1566  //BusActivation* pbsu_activation=(BusActivation*)actdata;
1567 
1568  _dbus_verbose("Entry\n");
1569  _dbus_verbose("Try to set label to process from connection\n");
1570 
1571  _dbus_verbose("actdata=%p, connection=%p, pid=%d\n",
1572  actdata,connection,pid);
1573 
1574  pdpl=dbus_connection_pdplinux_get_pdpl(connection);
1575  _dbus_pdplinux_show_text_label_info2("Connection",pdpl);
1576 
1577 #ifdef PDP_FORCE_SET_LABEL_AT_ACTIVATION_TIME
1578  if (0!=pdp_set_pid(pid,pdpl))
1579  _dbus_verbose("pdp_set_pid failed!\n");
1580  else
1581  res=TRUE;
1582 #else
1583  _dbus_verbose("Set label skipped by configuration\n");
1584  _dbus_verbose("Exit\n");
1585 #endif
1586 
1587  if (pdpl) pdpl_put(pdpl);
1588  return res;
1589 }
1590 #endif
1591 
_dbus_babysitter_ref
DBusBabysitter * _dbus_babysitter_ref(DBusBabysitter *sitter)
Increment the reference count on the babysitter object.
Definition: dbus-spawn.c:311
_dbus_watch_list_add_watch
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:382
_dbus_watch_list_new
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
Definition: dbus-watch.c:232
_DBUS_N_ELEMENTS
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
Definition: dbus-internals.h:188
DBusBabysitter::have_exec_errnum
unsigned int have_exec_errnum
True if we have an error code from exec()
Definition: dbus-spawn.c:273
DBusPollFD::revents
short revents
Events that occurred.
Definition: dbus-sysdeps.h:407
READ_STATUS_OK
@ READ_STATUS_OK
Read succeeded.
Definition: dbus-spawn.c:74
_dbus_babysitter_get_child_exited
dbus_bool_t _dbus_babysitter_get_child_exited(DBusBabysitter *sitter)
Checks whether the child has exited, without blocking.
Definition: dbus-spawn.c:725
DBusBabysitter::have_child_status
unsigned int have_child_status
True if child status has been reaped.
Definition: dbus-spawn.c:271
DBusBabysitter::status
int status
Exit status code.
Definition: dbus-spawn.c:270
_dbus_watch_list_remove_watch
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:415
_dbus_babysitter_set_child_exit_error
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:774
DBusFreeFunction
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
Definition: dbus-memory.h:63
DBusPollFD::events
short events
Events to poll for.
Definition: dbus-sysdeps.h:406
DBusBabysitter::log_name
char * log_name
the name under which to log messages about this process being spawned
Definition: dbus-spawn-win.c:67
DBUS_ERROR_SPAWN_CHILD_SIGNALED
#define DBUS_ERROR_SPAWN_CHILD_SIGNALED
While starting a new process, the child exited on a signal.
Definition: dbus-protocol.h:435
DBusWatch
Implementation of DBusWatch.
Definition: dbus-watch.c:41
_dbus_spawn_async_with_babysitter
dbus_bool_t _dbus_spawn_async_with_babysitter(DBusBabysitter **sitter_p, const char *log_name, char *const *argv, char **env, DBusSpawnFlags flags, DBusSpawnChildSetupFunc child_setup, void *user_data, DBusError *error)
Spawns a new process.
Definition: dbus-spawn.c:1273
DBUS_ERROR_SPAWN_CHILD_EXITED
#define DBUS_ERROR_SPAWN_CHILD_EXITED
While starting a new process, the child exited with a status code.
Definition: dbus-protocol.h:433
_dbus_babysitter_set_watch_functions
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:832
DBusConnection
Implementation details of DBusConnection.
Definition: dbus-connection.c:257
READ_STATUS_ERROR
@ READ_STATUS_ERROR
Some kind of error.
Definition: dbus-spawn.c:75
DBusBabysitter::sitter_pid
pid_t sitter_pid
PID Of the babysitter.
Definition: dbus-spawn.c:258
DBUS_ERROR_SPAWN_FAILED
#define DBUS_ERROR_SPAWN_FAILED
While starting a new process, something went wrong.
Definition: dbus-protocol.h:437
TRUE
#define TRUE
Expands to "1".
DBUS_WATCH_READABLE
@ DBUS_WATCH_READABLE
As in POLLIN.
Definition: dbus-connection.h:61
WRITE_END
#define WRITE_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:894
DBUS_WATCH_ERROR
@ DBUS_WATCH_ERROR
As in POLLERR (can't watch for this, but can be present in current state passed to dbus_watch_handle(...
Definition: dbus-connection.h:63
DBUS_ERROR_FAILED
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
Definition: dbus-protocol.h:368
DBUS_ERROR_SPAWN_EXEC_FAILED
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
Definition: dbus-protocol.h:429
READ_STATUS_EOF
@ READ_STATUS_EOF
EOF returned.
Definition: dbus-spawn.c:76
DBusAddWatchFunction
dbus_bool_t(* DBusAddWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus needs a new watch to be monitored by the main loop.
Definition: dbus-connection.h:92
_dbus_watch_unref
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
DBusBabysitter::error_pipe_from_child
int error_pipe_from_child
Connection to the process that does the exec()
Definition: dbus-spawn.c:256
dbus_free
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:702
_DBUS_POLLERR
#define _DBUS_POLLERR
Error condition.
Definition: dbus-sysdeps.h:417
_dbus_set_signal_handler
void _dbus_set_signal_handler(int sig, DBusSignalHandler handler)
Installs a UNIX signal handler.
Definition: dbus-sysdeps-util-unix.c:564
DBusPollFD::fd
DBusPollable fd
File descriptor.
Definition: dbus-sysdeps.h:405
dbus_watch_get_socket
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:594
DBusSocket
Socket interface.
Definition: dbus-sysdeps.h:181
DBusBabysitter
Babysitter implementation details.
Definition: dbus-spawn-win.c:62
FALSE
#define FALSE
Expands to "0".
DBusBabysitter::error_watch
DBusWatch * error_watch
Error pipe watch.
Definition: dbus-spawn.c:263
DBusPollFD
Definition: dbus-sysdeps.h:404
DBUS_ERROR_NO_MEMORY
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
Definition: dbus-protocol.h:370
DBusBabysitter::have_fork_errnum
unsigned int have_fork_errnum
True if we have an error code from fork()
Definition: dbus-spawn.c:272
DBUS_ERROR_INIT
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition: dbus-errors.h:62
_dbus_fd_set_close_on_exec
void _dbus_fd_set_close_on_exec(int fd)
Sets the file descriptor to be close on exec.
Definition: dbus-sysdeps-unix.c:3459
_dbus_poll
int _dbus_poll(DBusPollFD *fds, int n_fds, int timeout_milliseconds)
Wrapper for poll().
Definition: dbus-sysdeps-unix.c:3093
_dbus_assert_not_reached
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
Definition: dbus-internals.h:163
ReadStatus
ReadStatus
Enumeration for status of a read()
Definition: dbus-spawn.c:73
DBusBabysitter::watches
DBusWatchList * watches
Watches.
Definition: dbus-spawn-win.c:78
DBusWatchList
DBusWatchList implementation details.
Definition: dbus-watch.c:215
DBusBabysitter::errnum
int errnum
Error number.
Definition: dbus-spawn.c:269
DBusBabysitter::grandchild_pid
pid_t grandchild_pid
PID of the grandchild.
Definition: dbus-spawn.c:259
DBUS_ERROR_SPAWN_FORK_FAILED
#define DBUS_ERROR_SPAWN_FORK_FAILED
While starting a new process, the fork() call failed.
Definition: dbus-protocol.h:431
_dbus_close_socket
dbus_bool_t _dbus_close_socket(DBusSocket fd, DBusError *error)
Closes a socket.
Definition: dbus-sysdeps-unix.c:290
READ_END
#define READ_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:892
DBusWatchToggledFunction
void(* DBusWatchToggledFunction)(DBusWatch *watch, void *data)
Called when dbus_watch_get_enabled() may return a different value than it did before.
Definition: dbus-connection.h:98
_dbus_assert
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
Definition: dbus-internals.h:152
dbus_error_free
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
_dbus_close
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
Definition: dbus-sysdeps-unix.c:3481
_dbus_babysitter_unref
void _dbus_babysitter_unref(DBusBabysitter *sitter)
Decrement the reference count on the babysitter object.
Definition: dbus-spawn.c:333
_dbus_socketpair
dbus_bool_t _dbus_socketpair(DBusSocket *fd1, DBusSocket *fd2, dbus_bool_t blocking, DBusError *error)
Creates pair of connect sockets (as in socketpair()).
Definition: dbus-sysdeps-unix.c:3638
_dbus_warn
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
Definition: dbus-internals.c:263
_dbus_strdup
char * _dbus_strdup(const char *str)
Duplicates a string.
Definition: dbus-internals.c:644
_dbus_getpid
dbus_pid_t _dbus_getpid(void)
Gets our process ID.
Definition: dbus-sysdeps-unix.c:2930
_dbus_watch_list_free
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
Definition: dbus-watch.c:249
DBusError
Object representing an exception.
Definition: dbus-errors.h:49
_dbus_watch_invalidate
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
_dbus_watch_list_set_functions
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
DBusBabysitter::socket_to_babysitter
DBusSocket socket_to_babysitter
Connection to the babysitter process.
Definition: dbus-spawn-win.c:75
dbus_set_error
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
DBUS_PID_FORMAT
#define DBUS_PID_FORMAT
an appropriate printf format for dbus_pid_t
Definition: dbus-sysdeps.h:152
_DBUS_POLLIN
#define _DBUS_POLLIN
There is data to read.
Definition: dbus-sysdeps.h:411
dbus_free_string_array
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:750
DBusBabysitter::sitter_watch
DBusWatch * sitter_watch
Sitter pipe watch.
Definition: dbus-spawn-win.c:79
DBusRemoveWatchFunction
void(* DBusRemoveWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus no longer needs a watch to be monitored by the main loop.
Definition: dbus-connection.h:104
DBusBabysitter::refcount
int refcount
Reference count.
Definition: dbus-spawn.c:250
LIVE_CHILDREN
#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:694
DBusError::message
const char * message
public error message field
Definition: dbus-errors.h:51
_DBUS_POLLHUP
#define _DBUS_POLLHUP
Hung up.
Definition: dbus-sysdeps.h:419
_dbus_babysitter_kill_child
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:703
dbus_new0
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:58
_dbus_watch_new
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.
Definition: dbus-watch.c:88
DBUS_WATCH_HANGUP
@ DBUS_WATCH_HANGUP
As in POLLHUP (can't watch for it, but can be present in current state passed to dbus_watch_handle())...
Definition: dbus-connection.h:68
_dbus_babysitter_get_child_exit_status
dbus_bool_t _dbus_babysitter_get_child_exit_status(DBusBabysitter *sitter, int *status)
Gets the exit status of the child.
Definition: dbus-spawn.c:750
dbus_bool_t
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
NULL
#define NULL
A null pointer, defined appropriately for C or C++.