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