D-Bus  1.13.7
dbus-spawn-win.c
1 #include <config.h>
2 
3 //#define SPAWN_DEBUG
4 
5 #if !defined(SPAWN_DEBUG) || defined(_MSC_VER)
6 #define PING()
7 #else
8 #define PING() fprintf (stderr, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__); fflush (stderr)
9 #endif
10 
11 #include <stdio.h>
12 
13 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
14 /* dbus-spawn-win32.c Wrapper around g_spawn
15  *
16  * Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
17  * Copyright (C) 2003 CodeFactory AB
18  * Copyright (C) 2005 Novell, Inc.
19  *
20  * Licensed under the Academic Free License version 2.1
21  *
22  * This program is free software; you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License as published by
24  * the Free Software Foundation; either version 2 of the License, or
25  * (at your option) any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License
33  * along with this program; if not, write to the Free Software
34  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
35  *
36  */
37 #include "dbus-spawn.h"
38 #include "dbus-sysdeps.h"
39 #include "dbus-sysdeps-win.h"
40 #include "dbus-internals.h"
41 #include "dbus-test.h"
42 #include "dbus-protocol.h"
43 
44 #define WIN32_LEAN_AND_MEAN
45 #include <windows.h>
46 //#define STRICT
47 //#include <windows.h>
48 //#undef STRICT
49 #include <winsock2.h>
50 #undef interface
51 
52 #include <stdlib.h>
53 
54 #ifndef DBUS_WINCE
55 #include <process.h>
56 #endif
57 
61 struct DBusBabysitter
62  {
64 
65  HANDLE start_sync_event;
66 
67  char *log_name;
68 
69  int argc;
70  char **argv;
71  char **envp;
72 
73  HANDLE thread_handle;
74  HANDLE child_handle;
75  DBusSocket socket_to_babysitter; /* Connection to the babysitter thread */
76  DBusSocket socket_to_main;
77 
80  DBusBabysitterFinishedFunc finished_cb;
81  void *finished_data;
82 
83  dbus_bool_t have_spawn_errno;
84  int spawn_errno;
86  int child_status;
87  };
88 
89 static void
90 _dbus_babysitter_trace_ref (DBusBabysitter *sitter,
91  int old_refcount,
92  int new_refcount,
93  const char *why)
94 {
95 #ifdef DBUS_ENABLE_VERBOSE_MODE
96  static int enabled = -1;
97 
98  _dbus_trace_ref ("DBusBabysitter", sitter, old_refcount, new_refcount, why,
99  "DBUS_BABYSITTER_TRACE", &enabled);
100 #endif
101 }
102 
103 static DBusBabysitter*
104 _dbus_babysitter_new (void)
105 {
106  DBusBabysitter *sitter;
107  dbus_int32_t old_refcount;
108 
109  sitter = dbus_new0 (DBusBabysitter, 1);
110  if (sitter == NULL)
111  return NULL;
112 
113  old_refcount = _dbus_atomic_inc (&sitter->refcount);
114 
115  _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, __FUNCTION__);
116 
117  sitter->start_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
118  if (sitter->start_sync_event == NULL)
119  {
120  _dbus_babysitter_unref (sitter);
121  return NULL;
122  }
123 
124  sitter->child_handle = NULL;
125 
126  sitter->socket_to_babysitter = sitter->socket_to_main = _dbus_socket_get_invalid ();
127 
128  sitter->argc = 0;
129  sitter->argv = NULL;
130  sitter->envp = NULL;
131 
132  sitter->watches = _dbus_watch_list_new ();
133  if (sitter->watches == NULL)
134  {
135  _dbus_babysitter_unref (sitter);
136  return NULL;
137  }
138 
139  sitter->have_spawn_errno = FALSE;
140  sitter->have_child_status = FALSE;
141 
142  return sitter;
143 }
144 
153 {
154  dbus_int32_t old_refcount;
155  PING();
156  _dbus_assert (sitter != NULL);
157 
158  old_refcount = _dbus_atomic_inc (&sitter->refcount);
159  _dbus_assert (old_refcount > 0);
160  _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, __FUNCTION__);
161 
162  return sitter;
163 }
164 
165 static void
166 close_socket_to_babysitter (DBusBabysitter *sitter)
167 {
168  _dbus_verbose ("Closing babysitter\n");
169 
170  if (sitter->sitter_watch != NULL)
171  {
172  _dbus_assert (sitter->watches != NULL);
176  sitter->sitter_watch = NULL;
177  }
178 
179  if (sitter->socket_to_babysitter.sock != INVALID_SOCKET)
180  {
182  sitter->socket_to_babysitter.sock = INVALID_SOCKET;
183  }
184 }
185 
191 void
193 {
194  int i;
195  dbus_int32_t old_refcount;
196 
197  PING();
198  _dbus_assert (sitter != NULL);
199 
200  old_refcount = _dbus_atomic_dec (&sitter->refcount);
201  _dbus_assert (old_refcount > 0);
202  _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount-1, __FUNCTION__);
203 
204  if (old_refcount == 1)
205  {
206  close_socket_to_babysitter (sitter);
207 
208  if (sitter->socket_to_main.sock != INVALID_SOCKET)
209  {
210  _dbus_close_socket (sitter->socket_to_main, NULL);
211  sitter->socket_to_main.sock = INVALID_SOCKET;
212  }
213 
214  PING();
215  if (sitter->argv != NULL)
216  {
217  for (i = 0; i < sitter->argc; i++)
218  if (sitter->argv[i] != NULL)
219  {
220  dbus_free (sitter->argv[i]);
221  sitter->argv[i] = NULL;
222  }
223  dbus_free (sitter->argv);
224  sitter->argv = NULL;
225  }
226 
227  if (sitter->envp != NULL)
228  {
229  char **e = sitter->envp;
230 
231  while (*e)
232  dbus_free (*e++);
233  dbus_free (sitter->envp);
234  sitter->envp = NULL;
235  }
236 
237  if (sitter->child_handle != NULL)
238  {
239  CloseHandle (sitter->child_handle);
240  sitter->child_handle = NULL;
241  }
242 
243  if (sitter->sitter_watch)
244  {
247  sitter->sitter_watch = NULL;
248  }
249 
250  if (sitter->watches)
251  _dbus_watch_list_free (sitter->watches);
252 
253  if (sitter->start_sync_event != NULL)
254  {
255  PING();
256  CloseHandle (sitter->start_sync_event);
257  sitter->start_sync_event = NULL;
258  }
259 
260  if (sitter->thread_handle)
261  {
262  CloseHandle (sitter->thread_handle);
263  sitter->thread_handle = NULL;
264  }
265 
266  dbus_free (sitter->log_name);
267 
268  dbus_free (sitter);
269  }
270 }
271 
272 void
274 {
275  PING();
276  if (sitter->child_handle == NULL)
277  return; /* child is already dead, or we're so hosed we'll never recover */
278 
279  PING();
280  TerminateProcess (sitter->child_handle, 12345);
281 }
282 
290 {
291  PING();
292  return (sitter->child_handle == NULL);
293 }
294 
309  int *status)
310 {
311  if (!_dbus_babysitter_get_child_exited (sitter))
312  _dbus_assert_not_reached ("Child has not exited");
313 
314  if (!sitter->have_child_status ||
315  sitter->child_status == STILL_ACTIVE)
316  return FALSE;
317 
318  *status = sitter->child_status;
319  return TRUE;
320 }
321 
331 void
333  DBusError *error)
334 {
335  PING();
336  if (!_dbus_babysitter_get_child_exited (sitter))
337  return;
338 
339  PING();
340  if (sitter->have_spawn_errno)
341  {
342  char *emsg = _dbus_win_error_string (sitter->spawn_errno);
344  "Failed to execute program %s: %s",
345  sitter->log_name, emsg);
346  _dbus_win_free_error_string (emsg);
347  }
348  else if (sitter->have_child_status)
349  {
350  PING();
352  "Process %s exited with status %d",
353  sitter->log_name, sitter->child_status);
354  }
355  else
356  {
357  PING();
359  "Process %s exited, status unknown",
360  sitter->log_name);
361  }
362  PING();
363 }
364 
367  DBusAddWatchFunction add_function,
368  DBusRemoveWatchFunction remove_function,
369  DBusWatchToggledFunction toggled_function,
370  void *data,
371  DBusFreeFunction free_data_function)
372 {
373  PING();
374  return _dbus_watch_list_set_functions (sitter->watches,
375  add_function,
376  remove_function,
377  toggled_function,
378  data,
379  free_data_function);
380 }
381 
382 static dbus_bool_t
383 handle_watch (DBusWatch *watch,
384  unsigned int condition,
385  void *data)
386 {
387  DBusBabysitter *sitter = data;
388 
389  /* On Unix dbus-spawn uses a babysitter *process*, thus it has to
390  * actually send the exit statuses, error codes and whatnot through
391  * sockets and/or pipes. On Win32, the babysitter is jus a thread,
392  * so it can set the status fields directly in the babysitter struct
393  * just fine. The socket pipe is used just so we can watch it with
394  * select(), as soon as anything is written to it we know that the
395  * babysitter thread has recorded the status in the babysitter
396  * struct.
397  */
398 
399  PING();
400  close_socket_to_babysitter (sitter);
401  PING();
402 
403  if (_dbus_babysitter_get_child_exited (sitter) &&
404  sitter->finished_cb != NULL)
405  {
406  sitter->finished_cb (sitter, sitter->finished_data);
407  sitter->finished_cb = NULL;
408  }
409 
410  return TRUE;
411 }
412 
413 /* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
414 static int
415 protect_argv (char * const *argv,
416  char ***new_argv)
417 {
418  int i;
419  int argc = 0;
420 
421  while (argv[argc])
422  ++argc;
423  *new_argv = dbus_malloc ((argc + 1) * sizeof (char *));
424  if (*new_argv == NULL)
425  return -1;
426 
427  for (i = 0; i < argc; i++)
428  (*new_argv)[i] = NULL;
429 
430  /* Quote each argv element if necessary, so that it will get
431  * reconstructed correctly in the C runtime startup code. Note that
432  * the unquoting algorithm in the C runtime is really weird, and
433  * rather different than what Unix shells do. See stdargv.c in the C
434  * runtime sources (in the Platform SDK, in src/crt).
435  *
436  * Note that an new_argv[0] constructed by this function should
437  * *not* be passed as the filename argument to a spawn* or exec*
438  * family function. That argument should be the real file name
439  * without any quoting.
440  */
441  for (i = 0; i < argc; i++)
442  {
443  const char *p = argv[i];
444  char *q;
445  int len = 0;
446  int need_dblquotes = FALSE;
447  while (*p)
448  {
449  if (*p == ' ' || *p == '\t')
450  need_dblquotes = TRUE;
451  else if (*p == '"')
452  len++;
453  else if (*p == '\\')
454  {
455  const char *pp = p;
456  while (*pp && *pp == '\\')
457  pp++;
458  if (*pp == '"')
459  len++;
460  }
461  len++;
462  p++;
463  }
464 
465  q = (*new_argv)[i] = dbus_malloc (len + need_dblquotes*2 + 1);
466 
467  if (q == NULL)
468  return -1;
469 
470 
471  p = argv[i];
472 
473  if (need_dblquotes)
474  *q++ = '"';
475 
476  while (*p)
477  {
478  if (*p == '"')
479  *q++ = '\\';
480  else if (*p == '\\')
481  {
482  const char *pp = p;
483  while (*pp && *pp == '\\')
484  pp++;
485  if (*pp == '"')
486  *q++ = '\\';
487  }
488  *q++ = *p;
489  p++;
490  }
491 
492  if (need_dblquotes)
493  *q++ = '"';
494  *q++ = '\0';
495  /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (*new_argv)[i]); */
496  }
497  (*new_argv)[argc] = NULL;
498 
499  return argc;
500 }
501 
502 
503 /* From GPGME, relicensed by g10 Code GmbH. */
504 static char *
505 compose_string (char **strings, char separator)
506 {
507  int i;
508  int n = 0;
509  char *buf;
510  char *p;
511 
512  if (!strings || !strings[0])
513  return 0;
514  for (i = 0; strings[i]; i++)
515  n += strlen (strings[i]) + 1;
516  n++;
517 
518  buf = p = malloc (n);
519  if (!buf)
520  return NULL;
521  for (i = 0; strings[i]; i++)
522  {
523  strcpy (p, strings[i]);
524  p += strlen (strings[i]);
525  *(p++) = separator;
526  }
527  p--;
528  *(p++) = '\0';
529  *p = '\0';
530 
531  return buf;
532 }
533 
534 static char *
535 build_commandline (char **argv)
536 {
537  return compose_string (argv, ' ');
538 }
539 
540 static char *
541 build_env_string (char** envp)
542 {
543  return compose_string (envp, '\0');
544 }
545 
546 HANDLE
547 _dbus_spawn_program (const char *name,
548  char **argv,
549  char **envp)
550 {
551  PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
552  STARTUPINFOA si;
553  char *arg_string, *env_string;
554  BOOL result;
555 
556 #ifdef DBUS_WINCE
557  if (argv && argv[0])
558  arg_string = build_commandline (argv + 1);
559  else
560  arg_string = NULL;
561 #else
562  arg_string = build_commandline (argv);
563 #endif
564  if (!arg_string)
565  return INVALID_HANDLE_VALUE;
566 
567  env_string = build_env_string(envp);
568 
569  memset (&si, 0, sizeof (si));
570  si.cb = sizeof (si);
571 
572 #ifdef DBUS_ENABLE_VERBOSE_MODE
573  {
574  char *s = compose_string (envp, ';');
575  _dbus_verbose ("spawning '%s'' with args: '%s' env: '%s'\n", name, arg_string, s);
576  free (s);
577  }
578 #endif
579 
580 #ifdef DBUS_WINCE
581  result = CreateProcessA (name, arg_string, NULL, NULL, FALSE, 0,
582 #else
583  result = CreateProcessA (NULL, arg_string, NULL, NULL, FALSE, 0,
584 #endif
585  (LPVOID)env_string, NULL, &si, &pi);
586  free (arg_string);
587  if (env_string)
588  free (env_string);
589 
590  if (!result)
591  return INVALID_HANDLE_VALUE;
592 
593  CloseHandle (pi.hThread);
594  return pi.hProcess;
595 }
596 
597 
598 static DWORD __stdcall
599 babysitter (void *parameter)
600 {
601  int ret = 0;
602  DBusBabysitter *sitter = (DBusBabysitter *) parameter;
603  HANDLE handle;
604 
605  PING();
606  _dbus_verbose ("babysitter: spawning %s\n", sitter->log_name);
607 
608  PING();
609  handle = _dbus_spawn_program (sitter->log_name, sitter->argv, sitter->envp);
610 
611  PING();
612  if (handle != INVALID_HANDLE_VALUE)
613  {
614  sitter->child_handle = handle;
615  }
616  else
617  {
618  sitter->child_handle = NULL;
619  sitter->have_spawn_errno = TRUE;
620  sitter->spawn_errno = GetLastError();
621  }
622 
623  PING();
624  SetEvent (sitter->start_sync_event);
625 
626  if (sitter->child_handle != NULL)
627  {
628  DWORD status;
629 
630  PING();
631  // wait until process finished
632  WaitForSingleObject (sitter->child_handle, INFINITE);
633 
634  PING();
635  ret = GetExitCodeProcess (sitter->child_handle, &status);
636  if (ret)
637  {
638  sitter->child_status = status;
639  sitter->have_child_status = TRUE;
640  }
641 
642  CloseHandle (sitter->child_handle);
643  sitter->child_handle = NULL;
644  }
645 
646  PING();
647  send (sitter->socket_to_main.sock, " ", 1, 0);
648 
649  _dbus_babysitter_unref (sitter);
650 
651  return ret ? 0 : 1;
652 }
653 
656  const char *log_name,
657  char * const *argv,
658  char **envp,
659  DBusSpawnFlags flags _DBUS_GNUC_UNUSED,
660  DBusSpawnChildSetupFunc child_setup _DBUS_GNUC_UNUSED,
661  void *user_data _DBUS_GNUC_UNUSED,
662  DBusError *error)
663 {
664  DBusBabysitter *sitter;
665  DWORD sitter_thread_id;
666 
667  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
668  _dbus_assert (argv[0] != NULL);
669 
670  if (sitter_p != NULL)
671  *sitter_p = NULL;
672 
673  PING();
674  sitter = _dbus_babysitter_new ();
675  if (sitter == NULL)
676  {
677  _DBUS_SET_OOM (error);
678  return FALSE;
679  }
680 
681  sitter->log_name = _dbus_strdup (log_name);
682  if (sitter->log_name == NULL && log_name != NULL)
683  {
684  _DBUS_SET_OOM (error);
685  goto out0;
686  }
687 
688  if (sitter->log_name == NULL)
689  sitter->log_name = _dbus_strdup (argv[0]);
690 
691  if (sitter->log_name == NULL)
692  {
693  _DBUS_SET_OOM (error);
694  goto out0;
695  }
696 
697  PING();
698  if (!_dbus_socketpair (&sitter->socket_to_babysitter,
699  &sitter->socket_to_main,
700  FALSE, error))
701  goto out0;
702 
705  TRUE, handle_watch, sitter, NULL);
706  PING();
707  if (sitter->sitter_watch == NULL)
708  {
709  _DBUS_SET_OOM (error);
710  goto out0;
711  }
712 
713  PING();
714  if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
715  {
716  /* we need to free it early so the destructor won't try to remove it
717  * without it having been added, which DBusLoop doesn't allow */
720  sitter->sitter_watch = NULL;
721 
722  _DBUS_SET_OOM (error);
723  goto out0;
724  }
725 
726  sitter->argc = protect_argv (argv, &sitter->argv);
727  if (sitter->argc == -1)
728  {
729  _DBUS_SET_OOM (error);
730  goto out0;
731  }
732  sitter->envp = envp;
733 
734  PING();
735  sitter->thread_handle = (HANDLE) CreateThread (NULL, 0, babysitter,
736  _dbus_babysitter_ref (sitter), 0, &sitter_thread_id);
737 
738  if (sitter->thread_handle == NULL)
739  {
740  PING();
742  "Failed to create new thread");
743  goto out0;
744  }
745 
746  PING();
747  WaitForSingleObject (sitter->start_sync_event, INFINITE);
748 
749  PING();
750  if (sitter_p != NULL)
751  *sitter_p = sitter;
752  else
753  _dbus_babysitter_unref (sitter);
754 
755  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
756 
757  PING();
758  return TRUE;
759 
760 out0:
761  _dbus_babysitter_unref (sitter);
762 
763  return FALSE;
764 }
765 
766 void
767 _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
768  DBusBabysitterFinishedFunc finished,
769  void *user_data)
770 {
771  sitter->finished_cb = finished;
772  sitter->finished_data = user_data;
773 }
774 
775 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
776 
777 void
778 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
779 {
780  /* The thread terminates after the child does. We want to wait for the thread,
781  * not just the child, to avoid data races and ensure that it has freed all
782  * its memory. */
783  WaitForSingleObject (sitter->thread_handle, INFINITE);
784 }
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:323
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:63
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:703
dbus_bool_t _dbus_socketpair(DBusSocket *fd1, DBusSocket *fd2, dbus_bool_t blocking, DBusError *error)
Creates pair of connect sockets (as in socketpair()).
void(* DBusWatchToggledFunction)(DBusWatch *watch, void *data)
Called when dbus_watch_get_enabled() may return a different value than it did before.
#define DBUS_ERROR_SPAWN_CHILD_EXITED
While starting a new process, the child exited with a status code.
int status
Exit status code.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
Definition: dbus-watch.c:249
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
Definition: dbus-watch.c:232
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.
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:295
Socket interface.
Definition: dbus-sysdeps.h:178
DBusWatchList * watches
Watches.
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:463
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:58
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_bool_t _dbus_babysitter_get_child_exit_status(DBusBabysitter *sitter, int *status)
Gets the exit status of the child.
void _dbus_babysitter_kill_child(DBusBabysitter *sitter)
Blocks until the babysitter process gives us the PID of the spawned grandchild, then kills the spawne...
Babysitter implementation details.
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
dbus_bool_t _dbus_spawn_async_with_babysitter(DBusBabysitter **sitter_p, const char *log_name, char *const *argv, char **env, DBusSpawnFlags flags, DBusSpawnChildSetupFunc child_setup, void *user_data, DBusError *error)
Spawns a new process.
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...
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
int refcount
Reference count.
unsigned int have_child_status
True if child status has been reaped.
#define TRUE
Expands to "1".
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - 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:381
dbus_bool_t(* DBusAddWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus needs a new watch to be monitored by the main loop.
void(* DBusRemoveWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus no longer needs a watch to be monitored by the main loop.
DBusWatchList implementation details.
Definition: dbus-watch.c:214
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:414
void _dbus_babysitter_unref(DBusBabysitter *sitter)
Decrement the reference count on the babysitter object.
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
#define DBUS_ERROR_SPAWN_FORK_FAILED
While starting a new process, the fork() call failed.
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 FALSE
Expands to "0".
void dbus_set_error_const(DBusError *error, const char *name, const char *message)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:243
As in POLLIN.
DBusSocket socket_to_babysitter
Connection to the babysitter process.
char * _dbus_strdup(const char *str)
Duplicates a string.
void _dbus_babysitter_set_child_exit_error(DBusBabysitter *sitter, DBusError *error)
Sets the DBusError with an explanation of why the spawned child process exited (on a signal...
DBusBabysitter * _dbus_babysitter_ref(DBusBabysitter *sitter)
Increment the reference count on the babysitter object.