D-Bus  1.6.8
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 
42 extern char **environ;
43 
49 /*
50  * I'm pretty sure this whole spawn file could be made simpler,
51  * if you thought about it a bit.
52  */
53 
57 typedef enum
58 {
62 } ReadStatus;
63 
64 static ReadStatus
65 read_ints (int fd,
66  int *buf,
67  int n_ints_in_buf,
68  int *n_ints_read,
69  DBusError *error)
70 {
71  size_t bytes = 0;
72  ReadStatus retval;
73 
74  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
75 
76  retval = READ_STATUS_OK;
77 
78  while (TRUE)
79  {
80  ssize_t chunk;
81  size_t to_read;
82 
83  to_read = sizeof (int) * n_ints_in_buf - bytes;
84 
85  if (to_read == 0)
86  break;
87 
88  again:
89 
90  chunk = read (fd,
91  ((char*)buf) + bytes,
92  to_read);
93 
94  if (chunk < 0 && errno == EINTR)
95  goto again;
96 
97  if (chunk < 0)
98  {
99  dbus_set_error (error,
101  "Failed to read from child pipe (%s)",
102  _dbus_strerror (errno));
103 
104  retval = READ_STATUS_ERROR;
105  break;
106  }
107  else if (chunk == 0)
108  {
109  retval = READ_STATUS_EOF;
110  break; /* EOF */
111  }
112  else /* chunk > 0 */
113  bytes += chunk;
114  }
115 
116  *n_ints_read = (int)(bytes / sizeof(int));
117 
118  return retval;
119 }
120 
121 static ReadStatus
122 read_pid (int fd,
123  pid_t *buf,
124  DBusError *error)
125 {
126  size_t bytes = 0;
127  ReadStatus retval;
128 
129  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
130 
131  retval = READ_STATUS_OK;
132 
133  while (TRUE)
134  {
135  ssize_t chunk;
136  size_t to_read;
137 
138  to_read = sizeof (pid_t) - bytes;
139 
140  if (to_read == 0)
141  break;
142 
143  again:
144 
145  chunk = read (fd,
146  ((char*)buf) + bytes,
147  to_read);
148  if (chunk < 0 && errno == EINTR)
149  goto again;
150 
151  if (chunk < 0)
152  {
153  dbus_set_error (error,
155  "Failed to read from child pipe (%s)",
156  _dbus_strerror (errno));
157 
158  retval = READ_STATUS_ERROR;
159  break;
160  }
161  else if (chunk == 0)
162  {
163  retval = READ_STATUS_EOF;
164  break; /* EOF */
165  }
166  else /* chunk > 0 */
167  bytes += chunk;
168  }
169 
170  return retval;
171 }
172 
173 /* The implementation uses an intermediate child between the main process
174  * and the grandchild. The grandchild is our spawned process. The intermediate
175  * child is a babysitter process; it keeps track of when the grandchild
176  * exits/crashes, and reaps the grandchild.
177  */
178 
179 /* Messages from children to parents */
180 enum
181 {
182  CHILD_EXITED, /* This message is followed by the exit status int */
183  CHILD_FORK_FAILED, /* Followed by errno */
184  CHILD_EXEC_FAILED, /* Followed by errno */
185  CHILD_PID /* Followed by pid_t */
186 };
187 
191 struct DBusBabysitter
192 {
193  int refcount;
195  char *executable;
200  pid_t sitter_pid;
208  DBusBabysitterFinishedFunc finished_cb;
209  void *finished_data;
210 
211  int errnum;
212  int status;
213  unsigned int have_child_status : 1;
214  unsigned int have_fork_errnum : 1;
215  unsigned int have_exec_errnum : 1;
216 };
217 
218 static DBusBabysitter*
219 _dbus_babysitter_new (void)
220 {
221  DBusBabysitter *sitter;
222 
223  sitter = dbus_new0 (DBusBabysitter, 1);
224  if (sitter == NULL)
225  return NULL;
226 
227  sitter->refcount = 1;
228 
229  sitter->socket_to_babysitter = -1;
230  sitter->error_pipe_from_child = -1;
231 
232  sitter->sitter_pid = -1;
233  sitter->grandchild_pid = -1;
234 
235  sitter->watches = _dbus_watch_list_new ();
236  if (sitter->watches == NULL)
237  goto failed;
238 
239  return sitter;
240 
241  failed:
242  _dbus_babysitter_unref (sitter);
243  return NULL;
244 }
245 
254 {
255  _dbus_assert (sitter != NULL);
256  _dbus_assert (sitter->refcount > 0);
257 
258  sitter->refcount += 1;
259 
260  return sitter;
261 }
262 
263 static void close_socket_to_babysitter (DBusBabysitter *sitter);
264 static void close_error_pipe_from_child (DBusBabysitter *sitter);
265 
274 void
276 {
277  _dbus_assert (sitter != NULL);
278  _dbus_assert (sitter->refcount > 0);
279 
280  sitter->refcount -= 1;
281  if (sitter->refcount == 0)
282  {
283  /* If we haven't forked other babysitters
284  * since this babysitter and socket were
285  * created then this close will cause the
286  * babysitter to wake up from poll with
287  * a hangup and then the babysitter will
288  * quit itself.
289  */
290  close_socket_to_babysitter (sitter);
291 
292  close_error_pipe_from_child (sitter);
293 
294  if (sitter->sitter_pid > 0)
295  {
296  int status;
297  int ret;
298 
299  /* It's possible the babysitter died on its own above
300  * from the close, or was killed randomly
301  * by some other process, so first try to reap it
302  */
303  ret = waitpid (sitter->sitter_pid, &status, WNOHANG);
304 
305  /* If we couldn't reap the child then kill it, and
306  * try again
307  */
308  if (ret == 0)
309  kill (sitter->sitter_pid, SIGKILL);
310 
311  again:
312  if (ret == 0)
313  ret = waitpid (sitter->sitter_pid, &status, 0);
314 
315  if (ret < 0)
316  {
317  if (errno == EINTR)
318  goto again;
319  else if (errno == ECHILD)
320  _dbus_warn ("Babysitter process not available to be reaped; should not happen\n");
321  else
322  _dbus_warn ("Unexpected error %d in waitpid() for babysitter: %s\n",
323  errno, _dbus_strerror (errno));
324  }
325  else
326  {
327  _dbus_verbose ("Reaped %ld, waiting for babysitter %ld\n",
328  (long) ret, (long) sitter->sitter_pid);
329 
330  if (WIFEXITED (sitter->status))
331  _dbus_verbose ("Babysitter exited with status %d\n",
332  WEXITSTATUS (sitter->status));
333  else if (WIFSIGNALED (sitter->status))
334  _dbus_verbose ("Babysitter received signal %d\n",
335  WTERMSIG (sitter->status));
336  else
337  _dbus_verbose ("Babysitter exited abnormally\n");
338  }
339 
340  sitter->sitter_pid = -1;
341  }
342 
343  if (sitter->watches)
344  _dbus_watch_list_free (sitter->watches);
345 
346  dbus_free (sitter->executable);
347 
348  dbus_free (sitter);
349  }
350 }
351 
352 static ReadStatus
353 read_data (DBusBabysitter *sitter,
354  int fd)
355 {
356  int what;
357  int got;
358  DBusError error = DBUS_ERROR_INIT;
359  ReadStatus r;
360 
361  r = read_ints (fd, &what, 1, &got, &error);
362 
363  switch (r)
364  {
365  case READ_STATUS_ERROR:
366  _dbus_warn ("Failed to read data from fd %d: %s\n", fd, error.message);
367  dbus_error_free (&error);
368  return r;
369 
370  case READ_STATUS_EOF:
371  return r;
372 
373  case READ_STATUS_OK:
374  break;
375  }
376 
377  if (got == 1)
378  {
379  switch (what)
380  {
381  case CHILD_EXITED:
382  case CHILD_FORK_FAILED:
383  case CHILD_EXEC_FAILED:
384  {
385  int arg;
386 
387  r = read_ints (fd, &arg, 1, &got, &error);
388 
389  switch (r)
390  {
391  case READ_STATUS_ERROR:
392  _dbus_warn ("Failed to read arg from fd %d: %s\n", fd, error.message);
393  dbus_error_free (&error);
394  return r;
395  case READ_STATUS_EOF:
396  return r;
397  case READ_STATUS_OK:
398  break;
399  }
400 
401  if (got == 1)
402  {
403  if (what == CHILD_EXITED)
404  {
405  sitter->have_child_status = TRUE;
406  sitter->status = arg;
407  sitter->errnum = 0;
408  _dbus_verbose ("recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n",
409  WIFEXITED (sitter->status), WIFSIGNALED (sitter->status),
410  WEXITSTATUS (sitter->status), WTERMSIG (sitter->status));
411  }
412  else if (what == CHILD_FORK_FAILED)
413  {
414  sitter->have_fork_errnum = TRUE;
415  sitter->errnum = arg;
416  _dbus_verbose ("recorded fork errnum %d\n", sitter->errnum);
417  }
418  else if (what == CHILD_EXEC_FAILED)
419  {
420  sitter->have_exec_errnum = TRUE;
421  sitter->errnum = arg;
422  _dbus_verbose ("recorded exec errnum %d\n", sitter->errnum);
423  }
424  }
425  }
426  break;
427  case CHILD_PID:
428  {
429  pid_t pid = -1;
430 
431  r = read_pid (fd, &pid, &error);
432 
433  switch (r)
434  {
435  case READ_STATUS_ERROR:
436  _dbus_warn ("Failed to read PID from fd %d: %s\n", fd, error.message);
437  dbus_error_free (&error);
438  return r;
439  case READ_STATUS_EOF:
440  return r;
441  case READ_STATUS_OK:
442  break;
443  }
444 
445  sitter->grandchild_pid = pid;
446 
447  _dbus_verbose ("recorded grandchild pid %d\n", sitter->grandchild_pid);
448  }
449  break;
450  default:
451  _dbus_warn ("Unknown message received from babysitter process\n");
452  break;
453  }
454  }
455 
456  return r;
457 }
458 
459 static void
460 close_socket_to_babysitter (DBusBabysitter *sitter)
461 {
462  _dbus_verbose ("Closing babysitter\n");
463 
464  if (sitter->sitter_watch != NULL)
465  {
466  _dbus_assert (sitter->watches != NULL);
470  sitter->sitter_watch = NULL;
471  }
472 
473  if (sitter->socket_to_babysitter >= 0)
474  {
476  sitter->socket_to_babysitter = -1;
477  }
478 }
479 
480 static void
481 close_error_pipe_from_child (DBusBabysitter *sitter)
482 {
483  _dbus_verbose ("Closing child error\n");
484 
485  if (sitter->error_watch != NULL)
486  {
487  _dbus_assert (sitter->watches != NULL);
490  _dbus_watch_unref (sitter->error_watch);
491  sitter->error_watch = NULL;
492  }
493 
494  if (sitter->error_pipe_from_child >= 0)
495  {
497  sitter->error_pipe_from_child = -1;
498  }
499 }
500 
501 static void
502 handle_babysitter_socket (DBusBabysitter *sitter,
503  int revents)
504 {
505  /* Even if we have POLLHUP, we want to keep reading
506  * data until POLLIN goes away; so this function only
507  * looks at HUP/ERR if no IN is set.
508  */
509  if (revents & _DBUS_POLLIN)
510  {
511  _dbus_verbose ("Reading data from babysitter\n");
512  if (read_data (sitter, sitter->socket_to_babysitter) != READ_STATUS_OK)
513  close_socket_to_babysitter (sitter);
514  }
515  else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
516  {
517  close_socket_to_babysitter (sitter);
518  }
519 }
520 
521 static void
522 handle_error_pipe (DBusBabysitter *sitter,
523  int revents)
524 {
525  if (revents & _DBUS_POLLIN)
526  {
527  _dbus_verbose ("Reading data from child error\n");
528  if (read_data (sitter, sitter->error_pipe_from_child) != READ_STATUS_OK)
529  close_error_pipe_from_child (sitter);
530  }
531  else if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
532  {
533  close_error_pipe_from_child (sitter);
534  }
535 }
536 
537 /* returns whether there were any poll events handled */
538 static dbus_bool_t
539 babysitter_iteration (DBusBabysitter *sitter,
540  dbus_bool_t block)
541 {
542  DBusPollFD fds[2];
543  int i;
544  dbus_bool_t descriptors_ready;
545 
546  descriptors_ready = FALSE;
547 
548  i = 0;
549 
550  if (sitter->error_pipe_from_child >= 0)
551  {
552  fds[i].fd = sitter->error_pipe_from_child;
553  fds[i].events = _DBUS_POLLIN;
554  fds[i].revents = 0;
555  ++i;
556  }
557 
558  if (sitter->socket_to_babysitter >= 0)
559  {
560  fds[i].fd = sitter->socket_to_babysitter;
561  fds[i].events = _DBUS_POLLIN;
562  fds[i].revents = 0;
563  ++i;
564  }
565 
566  if (i > 0)
567  {
568  int ret;
569 
570  do
571  {
572  ret = _dbus_poll (fds, i, 0);
573  }
574  while (ret < 0 && errno == EINTR);
575 
576  if (ret == 0 && block)
577  {
578  do
579  {
580  ret = _dbus_poll (fds, i, -1);
581  }
582  while (ret < 0 && errno == EINTR);
583  }
584 
585  if (ret > 0)
586  {
587  descriptors_ready = TRUE;
588 
589  while (i > 0)
590  {
591  --i;
592  if (fds[i].fd == sitter->error_pipe_from_child)
593  handle_error_pipe (sitter, fds[i].revents);
594  else if (fds[i].fd == sitter->socket_to_babysitter)
595  handle_babysitter_socket (sitter, fds[i].revents);
596  }
597  }
598  }
599 
600  return descriptors_ready;
601 }
602 
607 #define LIVE_CHILDREN(sitter) ((sitter)->socket_to_babysitter >= 0 || (sitter)->error_pipe_from_child >= 0)
608 
615 void
617 {
618  /* be sure we have the PID of the child */
619  while (LIVE_CHILDREN (sitter) &&
620  sitter->grandchild_pid == -1)
621  babysitter_iteration (sitter, TRUE);
622 
623  _dbus_verbose ("Got child PID %ld for killing\n",
624  (long) sitter->grandchild_pid);
625 
626  if (sitter->grandchild_pid == -1)
627  return; /* child is already dead, or we're so hosed we'll never recover */
628 
629  kill (sitter->grandchild_pid, SIGKILL);
630 }
631 
639 {
640 
641  /* Be sure we're up-to-date */
642  while (LIVE_CHILDREN (sitter) &&
643  babysitter_iteration (sitter, FALSE))
644  ;
645 
646  /* We will have exited the babysitter when the child has exited */
647  return sitter->socket_to_babysitter < 0;
648 }
649 
664  int *status)
665 {
666  if (!_dbus_babysitter_get_child_exited (sitter))
667  _dbus_assert_not_reached ("Child has not exited");
668 
669  if (!sitter->have_child_status ||
670  !(WIFEXITED (sitter->status)))
671  return FALSE;
672 
673  *status = WEXITSTATUS (sitter->status);
674  return TRUE;
675 }
676 
686 void
688  DBusError *error)
689 {
690  if (!_dbus_babysitter_get_child_exited (sitter))
691  return;
692 
693  /* Note that if exec fails, we will also get a child status
694  * from the babysitter saying the child exited,
695  * so we need to give priority to the exec error
696  */
697  if (sitter->have_exec_errnum)
698  {
700  "Failed to execute program %s: %s",
701  sitter->executable, _dbus_strerror (sitter->errnum));
702  }
703  else if (sitter->have_fork_errnum)
704  {
706  "Failed to fork a new process %s: %s",
707  sitter->executable, _dbus_strerror (sitter->errnum));
708  }
709  else if (sitter->have_child_status)
710  {
711  if (WIFEXITED (sitter->status))
713  "Process %s exited with status %d",
714  sitter->executable, WEXITSTATUS (sitter->status));
715  else if (WIFSIGNALED (sitter->status))
717  "Process %s received signal %d",
718  sitter->executable, WTERMSIG (sitter->status));
719  else
721  "Process %s exited abnormally",
722  sitter->executable);
723  }
724  else
725  {
727  "Process %s exited, reason unknown",
728  sitter->executable);
729  }
730 }
731 
746  DBusAddWatchFunction add_function,
747  DBusRemoveWatchFunction remove_function,
748  DBusWatchToggledFunction toggled_function,
749  void *data,
750  DBusFreeFunction free_data_function)
751 {
752  return _dbus_watch_list_set_functions (sitter->watches,
753  add_function,
754  remove_function,
755  toggled_function,
756  data,
757  free_data_function);
758 }
759 
760 static dbus_bool_t
761 handle_watch (DBusWatch *watch,
762  unsigned int condition,
763  void *data)
764 {
765  DBusBabysitter *sitter = _dbus_babysitter_ref (data);
766  int revents;
767  int fd;
768 
769  revents = 0;
770  if (condition & DBUS_WATCH_READABLE)
771  revents |= _DBUS_POLLIN;
772  if (condition & DBUS_WATCH_ERROR)
773  revents |= _DBUS_POLLERR;
774  if (condition & DBUS_WATCH_HANGUP)
775  revents |= _DBUS_POLLHUP;
776 
777  fd = dbus_watch_get_socket (watch);
778 
779  if (fd == sitter->error_pipe_from_child)
780  handle_error_pipe (sitter, revents);
781  else if (fd == sitter->socket_to_babysitter)
782  handle_babysitter_socket (sitter, revents);
783 
784  while (LIVE_CHILDREN (sitter) &&
785  babysitter_iteration (sitter, FALSE))
786  ;
787 
788  /* fd.o #32992: if the handle_* methods closed their sockets, they previously
789  * didn't always remove the watches. Check that we don't regress. */
790  _dbus_assert (sitter->socket_to_babysitter != -1 || sitter->sitter_watch == NULL);
791  _dbus_assert (sitter->error_pipe_from_child != -1 || sitter->error_watch == NULL);
792 
793  if (_dbus_babysitter_get_child_exited (sitter) &&
794  sitter->finished_cb != NULL)
795  {
796  sitter->finished_cb (sitter, sitter->finished_data);
797  sitter->finished_cb = NULL;
798  }
799 
800  _dbus_babysitter_unref (sitter);
801  return TRUE;
802 }
803 
805 #define READ_END 0
806 
807 #define WRITE_END 1
808 
809 
810 /* Avoids a danger in threaded situations (calling close()
811  * on a file descriptor twice, and another thread has
812  * re-opened it since the first close)
813  */
814 static int
815 close_and_invalidate (int *fd)
816 {
817  int ret;
818 
819  if (*fd < 0)
820  return -1;
821  else
822  {
823  ret = _dbus_close_socket (*fd, NULL);
824  *fd = -1;
825  }
826 
827  return ret;
828 }
829 
830 static dbus_bool_t
831 make_pipe (int p[2],
832  DBusError *error)
833 {
834  int retval;
835 
836 #ifdef HAVE_PIPE2
837  dbus_bool_t cloexec_done;
838 
839  retval = pipe2 (p, O_CLOEXEC);
840  cloexec_done = retval >= 0;
841 
842  /* Check if kernel seems to be too old to know pipe2(). We assume
843  that if pipe2 is available, O_CLOEXEC is too. */
844  if (retval < 0 && errno == ENOSYS)
845 #endif
846  {
847  retval = pipe(p);
848  }
849 
850  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
851 
852  if (retval < 0)
853  {
854  dbus_set_error (error,
856  "Failed to create pipe for communicating with child process (%s)",
857  _dbus_strerror (errno));
858  return FALSE;
859  }
860 
861 #ifdef HAVE_PIPE2
862  if (!cloexec_done)
863 #endif
864  {
867  }
868 
869  return TRUE;
870 }
871 
872 static void
873 do_write (int fd, const void *buf, size_t count)
874 {
875  size_t bytes_written;
876  int ret;
877 
878  bytes_written = 0;
879 
880  again:
881 
882  ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written);
883 
884  if (ret < 0)
885  {
886  if (errno == EINTR)
887  goto again;
888  else
889  {
890  _dbus_warn ("Failed to write data to pipe!\n");
891  exit (1); /* give up, we suck */
892  }
893  }
894  else
895  bytes_written += ret;
896 
897  if (bytes_written < count)
898  goto again;
899 }
900 
901 static void
902 write_err_and_exit (int fd, int msg)
903 {
904  int en = errno;
905 
906  do_write (fd, &msg, sizeof (msg));
907  do_write (fd, &en, sizeof (en));
908 
909  exit (1);
910 }
911 
912 static void
913 write_pid (int fd, pid_t pid)
914 {
915  int msg = CHILD_PID;
916 
917  do_write (fd, &msg, sizeof (msg));
918  do_write (fd, &pid, sizeof (pid));
919 }
920 
921 static void
922 write_status_and_exit (int fd, int status)
923 {
924  int msg = CHILD_EXITED;
925 
926  do_write (fd, &msg, sizeof (msg));
927  do_write (fd, &status, sizeof (status));
928 
929  exit (0);
930 }
931 
932 static void
933 do_exec (int child_err_report_fd,
934  char **argv,
935  char **envp,
936  DBusSpawnChildSetupFunc child_setup,
937  void *user_data)
938 {
939 #ifdef DBUS_BUILD_TESTS
940  int i, max_open;
941 #endif
942 
943  _dbus_verbose_reset ();
944  _dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n",
945  _dbus_getpid ());
946 
947  if (child_setup)
948  (* child_setup) (user_data);
949 
950 #ifdef DBUS_BUILD_TESTS
951  max_open = sysconf (_SC_OPEN_MAX);
952 
953  for (i = 3; i < max_open; i++)
954  {
955  int retval;
956 
957  if (i == child_err_report_fd)
958  continue;
959 
960  retval = fcntl (i, F_GETFD);
961 
962  if (retval != -1 && !(retval & FD_CLOEXEC))
963  _dbus_warn ("Fd %d did not have the close-on-exec flag set!\n", i);
964  }
965 #endif
966 
967  if (envp == NULL)
968  {
969  _dbus_assert (environ != NULL);
970 
971  envp = environ;
972  }
973 
974  execve (argv[0], argv, envp);
975 
976  /* Exec failed */
977  write_err_and_exit (child_err_report_fd,
978  CHILD_EXEC_FAILED);
979 }
980 
981 static void
982 check_babysit_events (pid_t grandchild_pid,
983  int parent_pipe,
984  int revents)
985 {
986  pid_t ret;
987  int status;
988 
989  do
990  {
991  ret = waitpid (grandchild_pid, &status, WNOHANG);
992  /* The man page says EINTR can't happen with WNOHANG,
993  * but there are reports of it (maybe only with valgrind?)
994  */
995  }
996  while (ret < 0 && errno == EINTR);
997 
998  if (ret == 0)
999  {
1000  _dbus_verbose ("no child exited\n");
1001 
1002  ; /* no child exited */
1003  }
1004  else if (ret < 0)
1005  {
1006  /* This isn't supposed to happen. */
1007  _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s\n",
1008  _dbus_strerror (errno));
1009  exit (1);
1010  }
1011  else if (ret == grandchild_pid)
1012  {
1013  /* Child exited */
1014  _dbus_verbose ("reaped child pid %ld\n", (long) ret);
1015 
1016  write_status_and_exit (parent_pipe, status);
1017  }
1018  else
1019  {
1020  _dbus_warn ("waitpid() reaped pid %d that we've never heard of\n",
1021  (int) ret);
1022  exit (1);
1023  }
1024 
1025  if (revents & _DBUS_POLLIN)
1026  {
1027  _dbus_verbose ("babysitter got POLLIN from parent pipe\n");
1028  }
1029 
1030  if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP))
1031  {
1032  /* Parent is gone, so we just exit */
1033  _dbus_verbose ("babysitter got POLLERR or POLLHUP from parent\n");
1034  exit (0);
1035  }
1036 }
1037 
1038 static int babysit_sigchld_pipe = -1;
1039 
1040 static void
1041 babysit_signal_handler (int signo)
1042 {
1043  char b = '\0';
1044  again:
1045  if (write (babysit_sigchld_pipe, &b, 1) <= 0)
1046  if (errno == EINTR)
1047  goto again;
1048 }
1049 
1050 static void
1051 babysit (pid_t grandchild_pid,
1052  int parent_pipe)
1053 {
1054  int sigchld_pipe[2];
1055 
1056  /* We don't exec, so we keep parent state, such as the pid that
1057  * _dbus_verbose() uses. Reset the pid here.
1058  */
1059  _dbus_verbose_reset ();
1060 
1061  /* I thought SIGCHLD would just wake up the poll, but
1062  * that didn't seem to work, so added this pipe.
1063  * Probably the pipe is more likely to work on busted
1064  * operating systems anyhow.
1065  */
1066  if (pipe (sigchld_pipe) < 0)
1067  {
1068  _dbus_warn ("Not enough file descriptors to create pipe in babysitter process\n");
1069  exit (1);
1070  }
1071 
1072  babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
1073 
1074  _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler);
1075 
1076  write_pid (parent_pipe, grandchild_pid);
1077 
1078  check_babysit_events (grandchild_pid, parent_pipe, 0);
1079 
1080  while (TRUE)
1081  {
1082  DBusPollFD pfds[2];
1083 
1084  pfds[0].fd = parent_pipe;
1085  pfds[0].events = _DBUS_POLLIN;
1086  pfds[0].revents = 0;
1087 
1088  pfds[1].fd = sigchld_pipe[READ_END];
1089  pfds[1].events = _DBUS_POLLIN;
1090  pfds[1].revents = 0;
1091 
1092  if (_dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1) < 0 && errno != EINTR)
1093  {
1094  _dbus_warn ("_dbus_poll() error: %s\n", strerror (errno));
1095  exit (1);
1096  }
1097 
1098  if (pfds[0].revents != 0)
1099  {
1100  check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
1101  }
1102  else if (pfds[1].revents & _DBUS_POLLIN)
1103  {
1104  char b;
1105  if (read (sigchld_pipe[READ_END], &b, 1) == -1)
1106  {
1107  /* ignore */
1108  }
1109  /* do waitpid check */
1110  check_babysit_events (grandchild_pid, parent_pipe, 0);
1111  }
1112  }
1113 
1114  exit (1);
1115 }
1116 
1138  char **argv,
1139  char **env,
1140  DBusSpawnChildSetupFunc child_setup,
1141  void *user_data,
1142  DBusError *error)
1143 {
1144  DBusBabysitter *sitter;
1145  int child_err_report_pipe[2] = { -1, -1 };
1146  int babysitter_pipe[2] = { -1, -1 };
1147  pid_t pid;
1148 
1149  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1150 
1151  if (sitter_p != NULL)
1152  *sitter_p = NULL;
1153 
1154  sitter = NULL;
1155 
1156  sitter = _dbus_babysitter_new ();
1157  if (sitter == NULL)
1158  {
1160  return FALSE;
1161  }
1162 
1163  sitter->executable = _dbus_strdup (argv[0]);
1164  if (sitter->executable == NULL)
1165  {
1167  goto cleanup_and_fail;
1168  }
1169 
1170  if (!make_pipe (child_err_report_pipe, error))
1171  goto cleanup_and_fail;
1172 
1173  if (!_dbus_full_duplex_pipe (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error))
1174  goto cleanup_and_fail;
1175 
1176  /* Setting up the babysitter is only useful in the parent,
1177  * but we don't want to run out of memory and fail
1178  * after we've already forked, since then we'd leak
1179  * child processes everywhere.
1180  */
1181  sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END],
1182  DBUS_WATCH_READABLE,
1183  TRUE, handle_watch, sitter, NULL);
1184  if (sitter->error_watch == NULL)
1185  {
1187  goto cleanup_and_fail;
1188  }
1189 
1190  if (!_dbus_watch_list_add_watch (sitter->watches, sitter->error_watch))
1191  {
1192  /* we need to free it early so the destructor won't try to remove it
1193  * without it having been added, which DBusLoop doesn't allow */
1195  _dbus_watch_unref (sitter->error_watch);
1196  sitter->error_watch = NULL;
1197 
1199  goto cleanup_and_fail;
1200  }
1201 
1202  sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0],
1203  DBUS_WATCH_READABLE,
1204  TRUE, handle_watch, sitter, NULL);
1205  if (sitter->sitter_watch == NULL)
1206  {
1208  goto cleanup_and_fail;
1209  }
1210 
1211  if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
1212  {
1213  /* we need to free it early so the destructor won't try to remove it
1214  * without it having been added, which DBusLoop doesn't allow */
1216  _dbus_watch_unref (sitter->sitter_watch);
1217  sitter->sitter_watch = NULL;
1218 
1220  goto cleanup_and_fail;
1221  }
1222 
1223  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1224 
1225  pid = fork ();
1226 
1227  if (pid < 0)
1228  {
1229  dbus_set_error (error,
1231  "Failed to fork (%s)",
1232  _dbus_strerror (errno));
1233  goto cleanup_and_fail;
1234  }
1235  else if (pid == 0)
1236  {
1237  /* Immediate child, this is the babysitter process. */
1238  int grandchild_pid;
1239 
1240  /* Be sure we crash if the parent exits
1241  * and we write to the err_report_pipe
1242  */
1243  signal (SIGPIPE, SIG_DFL);
1244 
1245  /* Close the parent's end of the pipes. */
1246  close_and_invalidate (&child_err_report_pipe[READ_END]);
1247  close_and_invalidate (&babysitter_pipe[0]);
1248 
1249  /* Create the child that will exec () */
1250  grandchild_pid = fork ();
1251 
1252  if (grandchild_pid < 0)
1253  {
1254  write_err_and_exit (babysitter_pipe[1],
1255  CHILD_FORK_FAILED);
1256  _dbus_assert_not_reached ("Got to code after write_err_and_exit()");
1257  }
1258  else if (grandchild_pid == 0)
1259  {
1260  do_exec (child_err_report_pipe[WRITE_END],
1261  argv,
1262  env,
1263  child_setup, user_data);
1264  _dbus_assert_not_reached ("Got to code after exec() - should have exited on error");
1265  }
1266  else
1267  {
1268  babysit (grandchild_pid, babysitter_pipe[1]);
1269  _dbus_assert_not_reached ("Got to code after babysit()");
1270  }
1271  }
1272  else
1273  {
1274  /* Close the uncared-about ends of the pipes */
1275  close_and_invalidate (&child_err_report_pipe[WRITE_END]);
1276  close_and_invalidate (&babysitter_pipe[1]);
1277 
1278  sitter->socket_to_babysitter = babysitter_pipe[0];
1279  babysitter_pipe[0] = -1;
1280 
1281  sitter->error_pipe_from_child = child_err_report_pipe[READ_END];
1282  child_err_report_pipe[READ_END] = -1;
1283 
1284  sitter->sitter_pid = pid;
1285 
1286  if (sitter_p != NULL)
1287  *sitter_p = sitter;
1288  else
1289  _dbus_babysitter_unref (sitter);
1290 
1291  dbus_free_string_array (env);
1292 
1293  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1294 
1295  return TRUE;
1296  }
1297 
1298  cleanup_and_fail:
1299 
1300  _DBUS_ASSERT_ERROR_IS_SET (error);
1301 
1302  close_and_invalidate (&child_err_report_pipe[READ_END]);
1303  close_and_invalidate (&child_err_report_pipe[WRITE_END]);
1304  close_and_invalidate (&babysitter_pipe[0]);
1305  close_and_invalidate (&babysitter_pipe[1]);
1306 
1307  if (sitter != NULL)
1308  _dbus_babysitter_unref (sitter);
1309 
1310  return FALSE;
1311 }
1312 
1313 void
1314 _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
1315  DBusBabysitterFinishedFunc finished,
1316  void *user_data)
1317 {
1318  sitter->finished_cb = finished;
1319  sitter->finished_data = user_data;
1320 }
1321 
1324 #ifdef DBUS_BUILD_TESTS
1325 
1326 static char *
1327 get_test_exec (const char *exe,
1328  DBusString *scratch_space)
1329 {
1330  const char *dbus_test_exec;
1331 
1332  dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
1333 
1334  if (dbus_test_exec == NULL)
1335  dbus_test_exec = DBUS_TEST_EXEC;
1336 
1337  if (!_dbus_string_init (scratch_space))
1338  return NULL;
1339 
1340  if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
1341  dbus_test_exec, exe, DBUS_EXEEXT))
1342  {
1343  _dbus_string_free (scratch_space);
1344  return NULL;
1345  }
1346 
1347  return _dbus_string_get_data (scratch_space);
1348 }
1349 
1350 static void
1351 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
1352 {
1353  while (LIVE_CHILDREN (sitter))
1354  babysitter_iteration (sitter, TRUE);
1355 }
1356 
1357 static dbus_bool_t
1358 check_spawn_nonexistent (void *data)
1359 {
1360  char *argv[4] = { NULL, NULL, NULL, NULL };
1361  DBusBabysitter *sitter = NULL;
1362  DBusError error = DBUS_ERROR_INIT;
1363 
1364  /*** Test launching nonexistent binary */
1365 
1366  argv[0] = "/this/does/not/exist/32542sdgafgafdg";
1367  if (_dbus_spawn_async_with_babysitter (&sitter, argv,
1368  NULL, NULL, NULL,
1369  &error))
1370  {
1371  _dbus_babysitter_block_for_child_exit (sitter);
1372  _dbus_babysitter_set_child_exit_error (sitter, &error);
1373  }
1374 
1375  if (sitter)
1376  _dbus_babysitter_unref (sitter);
1377 
1378  if (!dbus_error_is_set (&error))
1379  {
1380  _dbus_warn ("Did not get an error launching nonexistent executable\n");
1381  return FALSE;
1382  }
1383 
1384  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
1386  {
1387  _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
1388  error.name, error.message);
1389  dbus_error_free (&error);
1390  return FALSE;
1391  }
1392 
1393  dbus_error_free (&error);
1394 
1395  return TRUE;
1396 }
1397 
1398 static dbus_bool_t
1399 check_spawn_segfault (void *data)
1400 {
1401  char *argv[4] = { NULL, NULL, NULL, NULL };
1402  DBusBabysitter *sitter = NULL;
1403  DBusError error = DBUS_ERROR_INIT;
1404  DBusString argv0;
1405 
1406  /*** Test launching segfault binary */
1407 
1408  argv[0] = get_test_exec ("test-segfault", &argv0);
1409 
1410  if (argv[0] == NULL)
1411  {
1412  /* OOM was simulated, never mind */
1413  return TRUE;
1414  }
1415 
1416  if (_dbus_spawn_async_with_babysitter (&sitter, argv,
1417  NULL, NULL, NULL,
1418  &error))
1419  {
1420  _dbus_babysitter_block_for_child_exit (sitter);
1421  _dbus_babysitter_set_child_exit_error (sitter, &error);
1422  }
1423 
1424  _dbus_string_free (&argv0);
1425 
1426  if (sitter)
1427  _dbus_babysitter_unref (sitter);
1428 
1429  if (!dbus_error_is_set (&error))
1430  {
1431  _dbus_warn ("Did not get an error launching segfaulting binary\n");
1432  return FALSE;
1433  }
1434 
1435  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
1437  {
1438  _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
1439  error.name, error.message);
1440  dbus_error_free (&error);
1441  return FALSE;
1442  }
1443 
1444  dbus_error_free (&error);
1445 
1446  return TRUE;
1447 }
1448 
1449 static dbus_bool_t
1450 check_spawn_exit (void *data)
1451 {
1452  char *argv[4] = { NULL, NULL, NULL, NULL };
1453  DBusBabysitter *sitter = NULL;
1454  DBusError error = DBUS_ERROR_INIT;
1455  DBusString argv0;
1456 
1457  /*** Test launching exit failure binary */
1458 
1459  argv[0] = get_test_exec ("test-exit", &argv0);
1460 
1461  if (argv[0] == NULL)
1462  {
1463  /* OOM was simulated, never mind */
1464  return TRUE;
1465  }
1466 
1467  if (_dbus_spawn_async_with_babysitter (&sitter, argv,
1468  NULL, NULL, NULL,
1469  &error))
1470  {
1471  _dbus_babysitter_block_for_child_exit (sitter);
1472  _dbus_babysitter_set_child_exit_error (sitter, &error);
1473  }
1474 
1475  _dbus_string_free (&argv0);
1476 
1477  if (sitter)
1478  _dbus_babysitter_unref (sitter);
1479 
1480  if (!dbus_error_is_set (&error))
1481  {
1482  _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
1483  return FALSE;
1484  }
1485 
1486  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
1488  {
1489  _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
1490  error.name, error.message);
1491  dbus_error_free (&error);
1492  return FALSE;
1493  }
1494 
1495  dbus_error_free (&error);
1496 
1497  return TRUE;
1498 }
1499 
1500 static dbus_bool_t
1501 check_spawn_and_kill (void *data)
1502 {
1503  char *argv[4] = { NULL, NULL, NULL, NULL };
1504  DBusBabysitter *sitter = NULL;
1505  DBusError error = DBUS_ERROR_INIT;
1506  DBusString argv0;
1507 
1508  /*** Test launching sleeping binary then killing it */
1509 
1510  argv[0] = get_test_exec ("test-sleep-forever", &argv0);
1511 
1512  if (argv[0] == NULL)
1513  {
1514  /* OOM was simulated, never mind */
1515  return TRUE;
1516  }
1517 
1518  if (_dbus_spawn_async_with_babysitter (&sitter, argv,
1519  NULL, NULL, NULL,
1520  &error))
1521  {
1522  _dbus_babysitter_kill_child (sitter);
1523 
1524  _dbus_babysitter_block_for_child_exit (sitter);
1525 
1526  _dbus_babysitter_set_child_exit_error (sitter, &error);
1527  }
1528 
1529  _dbus_string_free (&argv0);
1530 
1531  if (sitter)
1532  _dbus_babysitter_unref (sitter);
1533 
1534  if (!dbus_error_is_set (&error))
1535  {
1536  _dbus_warn ("Did not get an error after killing spawned binary\n");
1537  return FALSE;
1538  }
1539 
1540  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
1542  {
1543  _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
1544  error.name, error.message);
1545  dbus_error_free (&error);
1546  return FALSE;
1547  }
1548 
1549  dbus_error_free (&error);
1550 
1551  return TRUE;
1552 }
1553 
1555 _dbus_spawn_test (const char *test_data_dir)
1556 {
1557  if (!_dbus_test_oom_handling ("spawn_nonexistent",
1558  check_spawn_nonexistent,
1559  NULL))
1560  return FALSE;
1561 
1562  if (!_dbus_test_oom_handling ("spawn_segfault",
1563  check_spawn_segfault,
1564  NULL))
1565  return FALSE;
1566 
1567  if (!_dbus_test_oom_handling ("spawn_exit",
1568  check_spawn_exit,
1569  NULL))
1570  return FALSE;
1571 
1572  if (!_dbus_test_oom_handling ("spawn_and_kill",
1573  check_spawn_and_kill,
1574  NULL))
1575  return FALSE;
1576 
1577  return TRUE;
1578 }
1579 #endif
dbus_bool_t dbus_error_has_name(const DBusError *error, const char *name)
Checks whether the error is set and has the given name.
Definition: dbus-errors.c:302
const char * message
public error message field
Definition: dbus-errors.h:51
#define DBUS_ERROR_SPAWN_FAILED
While starting a new process, something went wrong.
Implementation of DBusWatch.
Definition: dbus-watch.c:40
#define NULL
A null pointer, defined appropriately for C or C++.
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
Definition: dbus-memory.h:64
#define LIVE_CHILDREN(sitter)
Macro returns TRUE if the babysitter still has live sockets open to the babysitter child or the grand...
Definition: dbus-spawn.c:607
#define _DBUS_POLLHUP
Hung up.
Definition: dbus-sysdeps.h:291
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:215
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:700
DBusWatch * error_watch
Error pipe watch.
Definition: dbus-spawn.c:205
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
Definition: dbus-watch.c:232
void _dbus_watch_invalidate(DBusWatch *watch)
Clears the file descriptor from a now-invalid watch object so that no one tries to use it...
Definition: dbus-watch.c:169
#define DBUS_PID_FORMAT
an appropriate printf format for dbus_pid_t
Definition: dbus-sysdeps.h:112
#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:212
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
int socket_to_babysitter
Connection to the babysitter process.
dbus_bool_t _dbus_full_duplex_pipe(int *fd1, int *fd2, dbus_bool_t blocking, DBusError *error)
Creates a full-duplex pipe (as in socketpair()).
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition: dbus-errors.h:62
dbus_bool_t _dbus_watch_list_add_watch(DBusWatchList *watch_list, DBusWatch *watch)
Adds a new watch to the watch list, invoking the application DBusAddWatchFunction if appropriate...
Definition: dbus-watch.c:375
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:211
A portable struct pollfd wrapper.
Definition: dbus-sysdeps.h:299
#define _DBUS_POLLIN
There is data to read.
Definition: dbus-sysdeps.h:283
Read succeeded.
Definition: dbus-spawn.c:59
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
dbus_pid_t _dbus_getpid(void)
Gets our process ID.
char * executable
executable name to use in error messages
short events
Events to poll for.
Definition: dbus-sysdeps.h:302
dbus_bool_t _dbus_babysitter_get_child_exited(DBusBabysitter *sitter)
Checks whether the child has exited, without blocking.
Definition: dbus-spawn.c:638
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:183
dbus_bool_t _dbus_spawn_async_with_babysitter(DBusBabysitter **sitter_p, char **argv, char **env, DBusSpawnChildSetupFunc child_setup, void *user_data, DBusError *error)
Spawns a new process.
Definition: dbus-spawn.c:1137
dbus_bool_t(* DBusAddWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus needs a new watch to be monitored by the main loop.
DBusWatchList * watches
Watches.
void _dbus_fd_set_close_on_exec(intptr_t fd)
Sets the file descriptor to be close on exec.
#define DBUS_ERROR_SPAWN_CHILD_SIGNALED
While starting a new process, the child exited on a signal.
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:59
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
DBusWatch * sitter_watch
Sitter pipe watch.
DBUS_EXPORT int dbus_watch_get_socket(DBusWatch *watch)
Returns a socket to be watched, on UNIX this will return -1 if our transport is not socket-based so d...
Definition: dbus-watch.c:585
dbus_bool_t _dbus_babysitter_get_child_exit_status(DBusBabysitter *sitter, int *status)
Gets the exit status of the child.
Definition: dbus-spawn.c:663
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:616
Babysitter implementation details.
ReadStatus
Enumeration for status of a read()
Definition: dbus-spawn.c:57
int _dbus_poll(DBusPollFD *fds, int n_fds, int timeout_milliseconds)
Wrapper for poll().
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
pid_t sitter_pid
PID Of the babysitter.
Definition: dbus-spawn.c:200
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:1111
EOF returned.
Definition: dbus-spawn.c:61
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:745
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:201
#define _DBUS_N_ELEMENTS(array)
Computes the number of elements in a fixed-size array using sizeof().
int refcount
Reference count.
int fd
File descriptor.
Definition: dbus-sysdeps.h:301
As in POLLERR (can't watch for this, but can be present in current state passed to dbus_watch_handle(...
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:242
#define TRUE
Expands to "1".
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
As in POLLHUP (can't watch for it, but can be present in current state passed to dbus_watch_handle())...
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
const char * name
public error name field
Definition: dbus-errors.h:50
#define READ_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:805
DBusWatchList implementation details.
Definition: dbus-watch.c:214
void _dbus_babysitter_unref(DBusBabysitter *sitter)
Decrement the reference count on the babysitter object.
Definition: dbus-spawn.c:275
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:277
#define DBUS_ERROR_SPAWN_FORK_FAILED
While starting a new process, the fork() call failed.
void _dbus_set_signal_handler(int sig, DBusSignalHandler handler)
Installs a UNIX signal handler.
DBusWatch * _dbus_watch_new(int fd, unsigned int flags, dbus_bool_t enabled, DBusWatchHandler handler, void *data, DBusFreeFunction free_data_function)
Creates a new DBusWatch.
Definition: dbus-watch.c:88
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:748
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
unsigned int have_fork_errnum
True if we have an error code from fork()
Definition: dbus-spawn.c:214
#define FALSE
Expands to "0".
int error_pipe_from_child
Connection to the process that does the exec()
Definition: dbus-spawn.c:198
void _dbus_watch_unref(DBusWatch *watch)
Decrements the reference count of a DBusWatch object and finalizes the object if the count reaches ze...
Definition: dbus-watch.c:138
void(* DBusWatchToggledFunction)(DBusWatch *watch, void *data)
Called when dbus_watch_get_enabled() may return a different value than it did before.
As in POLLIN.
#define WRITE_END
Helps remember which end of the pipe is which.
Definition: dbus-spawn.c:807
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
Definition: dbus-watch.c:249
char * _dbus_strdup(const char *str)
Duplicates a string.
dbus_bool_t _dbus_close_socket(int fd, DBusError *error)
Closes a socket.
int errnum
Error number.
Definition: dbus-spawn.c:211
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:687
short revents
Events that occurred.
Definition: dbus-sysdeps.h:303
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:60
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:408
#define _DBUS_POLLERR
Error condition.
Definition: dbus-sysdeps.h:289
DBusBabysitter * _dbus_babysitter_ref(DBusBabysitter *sitter)
Increment the reference count on the babysitter object.
Definition: dbus-spawn.c:253