D-Bus  1.14.10
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__, _DBUS_FUNCTION_NAME, __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  char *log_name;
65 
66  HANDLE thread_handle;
67  HANDLE child_handle;
68  DBusSocket socket_to_babysitter; /* Connection to the babysitter thread */
69  DBusSocket socket_to_main;
70 
73  DBusBabysitterFinishedFunc finished_cb;
74  void *finished_data;
75 
76  dbus_bool_t have_spawn_errno;
77  int spawn_errno;
79  int child_status;
80  };
81 
82 static void
83 _dbus_babysitter_trace_ref (DBusBabysitter *sitter,
84  int old_refcount,
85  int new_refcount,
86  const char *why)
87 {
88 #ifdef DBUS_ENABLE_VERBOSE_MODE
89  static int enabled = -1;
90 
91  _dbus_trace_ref ("DBusBabysitter", sitter, old_refcount, new_refcount, why,
92  "DBUS_BABYSITTER_TRACE", &enabled);
93 #endif
94 }
95 
96 static DBusBabysitter*
97 _dbus_babysitter_new (void)
98 {
99  DBusBabysitter *sitter;
100  dbus_int32_t old_refcount;
101 
102  sitter = dbus_new0 (DBusBabysitter, 1);
103  if (sitter == NULL)
104  return NULL;
105 
106  old_refcount = _dbus_atomic_inc (&sitter->refcount);
107 
108  _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, _DBUS_FUNCTION_NAME);
109 
110  sitter->child_handle = NULL;
111 
112  sitter->socket_to_babysitter = sitter->socket_to_main = _dbus_socket_get_invalid ();
113 
114  sitter->watches = _dbus_watch_list_new ();
115  if (sitter->watches == NULL)
116  {
117  _dbus_babysitter_unref (sitter);
118  return NULL;
119  }
120 
121  sitter->have_spawn_errno = FALSE;
122  sitter->have_child_status = FALSE;
123 
124  return sitter;
125 }
126 
135 {
136  dbus_int32_t old_refcount;
137  PING();
138  _dbus_assert (sitter != NULL);
139 
140  old_refcount = _dbus_atomic_inc (&sitter->refcount);
141  _dbus_assert (old_refcount > 0);
142  _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, _DBUS_FUNCTION_NAME);
143 
144  return sitter;
145 }
146 
147 static void
148 close_socket_to_babysitter (DBusBabysitter *sitter)
149 {
150  _dbus_verbose ("Closing babysitter\n");
151 
152  if (sitter->sitter_watch != NULL)
153  {
154  _dbus_assert (sitter->watches != NULL);
158  sitter->sitter_watch = NULL;
159  }
160 
161  if (sitter->socket_to_babysitter.sock != INVALID_SOCKET)
162  {
164  sitter->socket_to_babysitter.sock = INVALID_SOCKET;
165  }
166 }
167 
173 void
175 {
176  dbus_int32_t old_refcount;
177 
178  PING();
179  _dbus_assert (sitter != NULL);
180 
181  old_refcount = _dbus_atomic_dec (&sitter->refcount);
182  _dbus_assert (old_refcount > 0);
183  _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount-1, _DBUS_FUNCTION_NAME);
184 
185  if (old_refcount == 1)
186  {
187  close_socket_to_babysitter (sitter);
188 
189  if (sitter->socket_to_main.sock != INVALID_SOCKET)
190  {
191  _dbus_close_socket (sitter->socket_to_main, NULL);
192  sitter->socket_to_main.sock = INVALID_SOCKET;
193  }
194 
195  if (sitter->child_handle != NULL)
196  {
197  CloseHandle (sitter->child_handle);
198  sitter->child_handle = NULL;
199  }
200 
201  if (sitter->sitter_watch)
202  {
205  sitter->sitter_watch = NULL;
206  }
207 
208  if (sitter->watches)
209  _dbus_watch_list_free (sitter->watches);
210 
211  if (sitter->thread_handle)
212  {
213  CloseHandle (sitter->thread_handle);
214  sitter->thread_handle = NULL;
215  }
216 
217  dbus_free (sitter->log_name);
218 
219  dbus_free (sitter);
220  }
221 }
222 
223 void
225 {
226  PING();
227  if (sitter->child_handle == NULL)
228  return; /* child is already dead, or we're so hosed we'll never recover */
229 
230  PING();
231  TerminateProcess (sitter->child_handle, 12345);
232 }
233 
241 {
242  PING();
243  return (sitter->child_handle == NULL);
244 }
245 
260  int *status)
261 {
262  if (!_dbus_babysitter_get_child_exited (sitter))
263  _dbus_assert_not_reached ("Child has not exited");
264 
265  if (!sitter->have_child_status ||
266  sitter->child_status == STILL_ACTIVE)
267  return FALSE;
268 
269  *status = sitter->child_status;
270  return TRUE;
271 }
272 
282 void
284  DBusError *error)
285 {
286  PING();
287  if (!_dbus_babysitter_get_child_exited (sitter))
288  return;
289 
290  PING();
291  if (sitter->have_spawn_errno)
292  {
293  char *emsg = _dbus_win_error_string (sitter->spawn_errno);
295  "Failed to execute program %s: %s",
296  sitter->log_name, emsg);
297  _dbus_win_free_error_string (emsg);
298  }
299  else if (sitter->have_child_status)
300  {
301  PING();
303  "Process %s exited with status %d",
304  sitter->log_name, sitter->child_status);
305  }
306  else
307  {
308  PING();
310  "Process %s exited, status unknown",
311  sitter->log_name);
312  }
313  PING();
314 }
315 
318  DBusAddWatchFunction add_function,
319  DBusRemoveWatchFunction remove_function,
320  DBusWatchToggledFunction toggled_function,
321  void *data,
322  DBusFreeFunction free_data_function)
323 {
324  PING();
325  return _dbus_watch_list_set_functions (sitter->watches,
326  add_function,
327  remove_function,
328  toggled_function,
329  data,
330  free_data_function);
331 }
332 
333 static dbus_bool_t
334 handle_watch (DBusWatch *watch,
335  unsigned int condition,
336  void *data)
337 {
338  DBusBabysitter *sitter = data;
339 
340  /* On Unix dbus-spawn uses a babysitter *process*, thus it has to
341  * actually send the exit statuses, error codes and whatnot through
342  * sockets and/or pipes. On Win32, the babysitter is jus a thread,
343  * so it can set the status fields directly in the babysitter struct
344  * just fine. The socket pipe is used just so we can watch it with
345  * select(), as soon as anything is written to it we know that the
346  * babysitter thread has recorded the status in the babysitter
347  * struct.
348  */
349 
350  PING();
351  close_socket_to_babysitter (sitter);
352  PING();
353 
354  if (_dbus_babysitter_get_child_exited (sitter) &&
355  sitter->finished_cb != NULL)
356  {
357  sitter->finished_cb (sitter, sitter->finished_data);
358  sitter->finished_cb = NULL;
359  }
360 
361  return TRUE;
362 }
363 
364 /* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
365 static int
366 protect_argv (char * const *argv,
367  char ***new_argv)
368 {
369  int i;
370  int argc = 0;
371  char **args = NULL;
372 
373  while (argv[argc])
374  ++argc;
375  args = dbus_malloc ((argc + 1) * sizeof (char *));
376  if (args == NULL)
377  return -1;
378 
379  for (i = 0; i < argc; i++)
380  (args)[i] = NULL;
381 
382  /* Quote each argv element if necessary, so that it will get
383  * reconstructed correctly in the C runtime startup code. Note that
384  * the unquoting algorithm in the C runtime is really weird, and
385  * rather different than what Unix shells do. See stdargv.c in the C
386  * runtime sources (in the Platform SDK, in src/crt).
387  *
388  * Note that an new_argv[0] constructed by this function should
389  * *not* be passed as the filename argument to a spawn* or exec*
390  * family function. That argument should be the real file name
391  * without any quoting.
392  */
393  for (i = 0; i < argc; i++)
394  {
395  const char *p = argv[i];
396  char *q;
397  int len = 0;
398  int need_dblquotes = FALSE;
399  while (*p)
400  {
401  if (*p == ' ' || *p == '\t')
402  need_dblquotes = TRUE;
403  else if (*p == '"')
404  len++;
405  else if (*p == '\\')
406  {
407  const char *pp = p;
408  while (*pp && *pp == '\\')
409  pp++;
410  if (*pp == '"')
411  len++;
412  }
413  len++;
414  p++;
415  }
416 
417  q = args[i] = dbus_malloc (len + need_dblquotes*2 + 1);
418 
419  if (q == NULL)
420  {
421  dbus_free_string_array (args);
422  return -1;
423  }
424 
425  p = argv[i];
426 
427  if (need_dblquotes)
428  *q++ = '"';
429 
430  while (*p)
431  {
432  if (*p == '"')
433  *q++ = '\\';
434  else if (*p == '\\')
435  {
436  const char *pp = p;
437  while (*pp && *pp == '\\')
438  pp++;
439  if (*pp == '"')
440  *q++ = '\\';
441  }
442  *q++ = *p;
443  p++;
444  }
445 
446  if (need_dblquotes)
447  *q++ = '"';
448  *q++ = '\0';
449  /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (args)[i]); */
450  }
451  args[argc] = NULL;
452  *new_argv = args;
453 
454  return argc;
455 }
456 
457 static dbus_bool_t
458 build_commandline (char **argv, DBusString *result)
459 {
460  return _dbus_string_append_strings (result, argv, ' ');
461 }
462 
463 static dbus_bool_t
464 build_env_block (char** envp, DBusString *result)
465 {
466  if (!_dbus_string_append_strings (result, envp, '\0'))
467  return FALSE;
468 
469  /* We need a double `\0` to terminate the environment block.
470  * DBusString provides one `\0` after the length-counted data,
471  * so add one more. */
472  if (!_dbus_string_append_byte (result, '\0'))
473  return FALSE;
474 
475  return TRUE;
476 }
477 
489 HANDLE
490 _dbus_spawn_program (const char *name,
491  char **argv,
492  char **envp,
493  dbus_bool_t inherit_handles,
494  DBusError *error)
495 {
496  PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
497  STARTUPINFOA si;
498  DBusString arg_string = _DBUS_STRING_INIT_INVALID;
499  DBusString env_block = _DBUS_STRING_INIT_INVALID;
500  BOOL result = FALSE;
501  char *env = NULL;
502 
503  if (!_dbus_string_init (&arg_string) || !_dbus_string_init (&env_block))
504  {
505  _DBUS_SET_OOM (error);
506  goto out;
507  }
508 
509 #ifdef DBUS_WINCE
510  if (argv && argv[0])
511  {
512  if (!build_commandline (argv + 1, &arg_string))
513  _DBUS_SET_OOM (error);
514  goto out;
515  }
516 #else
517  if (!build_commandline (argv, &arg_string))
518  {
519  _DBUS_SET_OOM (error);
520  goto out;
521  }
522 #endif
523  if (_dbus_string_get_length (&arg_string) == 0)
524  {
525  dbus_set_error (error, DBUS_ERROR_FAILED, "No arguments given to start '%s'", name);
526  goto out;
527  }
528 
529  if (envp != NULL)
530  {
531  if (!build_env_block (envp, &env_block))
532  {
533  _DBUS_SET_OOM (error);
534  goto out;
535  }
536  /* env_block consists of '0' terminated strings */
537  env = _dbus_string_get_data (&env_block);
538  }
539 
540  memset (&si, 0, sizeof (si));
541  si.cb = sizeof (si);
542 
543 #ifdef DBUS_ENABLE_VERBOSE_MODE
544  {
545  DBusString temp = _DBUS_STRING_INIT_INVALID;
546 
547  if (!_dbus_string_init (&temp))
548  {
549  _DBUS_SET_OOM (error);
550  goto out;
551  }
552 
553  if (!_dbus_string_append_strings (&temp, envp, ';'))
554  {
555  _dbus_string_free (&temp);
556  _DBUS_SET_OOM (error);
557  goto out;
558  }
559 
560  _dbus_verbose ("spawning '%s'' with args: '%s' env: '%s'\n", name,
561  _dbus_string_get_const_data (&arg_string),
562  _dbus_string_get_const_data (&temp));
563  _dbus_string_free (&temp);
564  }
565 #endif
566 
567 #ifdef DBUS_WINCE
568  result = CreateProcessA (name, _dbus_string_get_const_data (&arg_string), NULL, NULL, FALSE, 0,
569 #else
570  result = CreateProcessA (NULL, /* no application name */
571  _dbus_string_get_data (&arg_string),
572  NULL, /* no process attributes */
573  NULL, /* no thread attributes */
574  inherit_handles, /* inherit handles */
575  0, /* flags */
576 #endif
577  env, NULL, &si, &pi);
578  if (!result)
579  {
580  _dbus_win_set_error_from_last_error (error, "Unable to start '%s' with arguments '%s'",
581  name, _dbus_string_get_const_data (&arg_string));
582  goto out;
583  }
584 
585 out:
586  _DBUS_ASSERT_ERROR_XOR_BOOL (error, result);
587 
588  _dbus_string_free (&arg_string);
589  _dbus_string_free (&env_block);
590 
591  if (result)
592  {
593  CloseHandle (pi.hThread);
594  return pi.hProcess;
595  }
596 
597  return NULL;
598 }
599 
600 
601 static DWORD __stdcall
602 babysitter (void *parameter)
603 {
604  int ret = 0;
605  DBusBabysitter *sitter = (DBusBabysitter *) parameter;
606 
607  PING();
608  if (sitter->child_handle != NULL)
609  {
610  DWORD status;
611 
612  PING();
613  // wait until process finished
614  WaitForSingleObject (sitter->child_handle, INFINITE);
615 
616  PING();
617  ret = GetExitCodeProcess (sitter->child_handle, &status);
618  if (ret)
619  {
620  sitter->child_status = status;
621  sitter->have_child_status = TRUE;
622  }
623 
624  CloseHandle (sitter->child_handle);
625  sitter->child_handle = NULL;
626  }
627 
628  PING();
629  send (sitter->socket_to_main.sock, " ", 1, 0);
630 
631  _dbus_babysitter_unref (sitter);
632 
633  return ret ? 0 : 1;
634 }
635 
638  const char *log_name,
639  char * const *argv,
640  char * const *envp,
641  DBusSpawnFlags flags _DBUS_GNUC_UNUSED,
642  DBusSpawnChildSetupFunc child_setup _DBUS_GNUC_UNUSED,
643  void *user_data _DBUS_GNUC_UNUSED,
644  DBusError *error)
645 {
646  DBusBabysitter *sitter;
647  DWORD sitter_thread_id;
648  HANDLE handle;
649  int argc;
650  char **my_argv = NULL;
651  DBusError local_error = DBUS_ERROR_INIT;
652 
653  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
654  _dbus_assert (argv[0] != NULL);
655 
656  if (sitter_p != NULL)
657  *sitter_p = NULL;
658 
659  PING();
660  sitter = _dbus_babysitter_new ();
661  if (sitter == NULL)
662  {
663  _DBUS_SET_OOM (error);
664  return FALSE;
665  }
666 
667  sitter->log_name = _dbus_strdup (log_name);
668  if (sitter->log_name == NULL && log_name != NULL)
669  {
670  _DBUS_SET_OOM (error);
671  goto out0;
672  }
673 
674  if (sitter->log_name == NULL)
675  sitter->log_name = _dbus_strdup (argv[0]);
676 
677  if (sitter->log_name == NULL)
678  {
679  _DBUS_SET_OOM (error);
680  goto out0;
681  }
682 
683  PING();
684  if (!_dbus_socketpair (&sitter->socket_to_babysitter,
685  &sitter->socket_to_main,
686  FALSE, error))
687  goto out0;
688 
691  TRUE, handle_watch, sitter, NULL);
692  PING();
693  if (sitter->sitter_watch == NULL)
694  {
695  _DBUS_SET_OOM (error);
696  goto out0;
697  }
698 
699  PING();
700  if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
701  {
702  /* we need to free it early so the destructor won't try to remove it
703  * without it having been added, which DBusLoop doesn't allow */
706  sitter->sitter_watch = NULL;
707 
708  _DBUS_SET_OOM (error);
709  goto out0;
710  }
711 
712  argc = protect_argv (argv, &my_argv);
713  if (argc == -1)
714  {
715  _DBUS_SET_OOM (error);
716  goto out0;
717  }
718 
719  _dbus_verbose ("babysitter: spawn child '%s'\n", my_argv[0]);
720 
721  PING();
722  handle = _dbus_spawn_program (sitter->log_name, my_argv, (char **) envp, FALSE, &local_error);
723 
724  if (my_argv != NULL)
725  {
726  dbus_free_string_array (my_argv);
727  }
728 
729  PING();
730  if (handle == NULL)
731  {
732  if (dbus_error_has_name (&local_error, DBUS_ERROR_NO_MEMORY))
733  {
734  sitter->child_handle = NULL;
735  sitter->have_spawn_errno = TRUE;
736  sitter->spawn_errno = ERROR_NOT_ENOUGH_MEMORY;
737  dbus_move_error (&local_error, error);
738  }
739  else
740  {
741  sitter->child_handle = NULL;
742  sitter->have_spawn_errno = TRUE;
743  sitter->spawn_errno = GetLastError();
745  "Failed to spawn child: %s", local_error.message);
746  }
747  dbus_error_free (&local_error);
748  goto out0;
749  }
750  else
751  dbus_error_free (&local_error);
752 
753  sitter->child_handle = handle;
754 
755  PING();
756  sitter->thread_handle = (HANDLE) CreateThread (NULL, 0, babysitter,
757  _dbus_babysitter_ref (sitter), 0, &sitter_thread_id);
758 
759  if (sitter->thread_handle == NULL)
760  {
761  PING();
763  "Failed to create new thread");
764  goto out0;
765  }
766 
767  PING();
768  if (sitter_p != NULL)
769  *sitter_p = sitter;
770  else
771  _dbus_babysitter_unref (sitter);
772 
773  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
774 
775  PING();
776  return TRUE;
777 
778 out0:
779  _dbus_babysitter_unref (sitter);
780 
781  return FALSE;
782 }
783 
784 void
785 _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
786  DBusBabysitterFinishedFunc finished,
787  void *user_data)
788 {
789  sitter->finished_cb = finished;
790  sitter->finished_data = user_data;
791 }
792 
793 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
794 
795 void
796 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
797 {
798  /* The thread terminates after the child does. We want to wait for the thread,
799  * not just the child, to avoid data races and ensure that it has freed all
800  * its memory. */
801  WaitForSingleObject (sitter->thread_handle, INFINITE);
802 }
void(* DBusWatchToggledFunction)(DBusWatch *watch, void *data)
Called when dbus_watch_get_enabled() may return a different value than it did before.
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.
@ DBUS_WATCH_READABLE
As in POLLIN.
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition: dbus-errors.h:62
void dbus_move_error(DBusError *src, DBusError *dest)
Moves an error src into dest, freeing src and overwriting dest.
Definition: dbus-errors.c:279
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
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
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
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
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
dbus_bool_t _dbus_babysitter_get_child_exit_status(DBusBabysitter *sitter, int *status)
Gets the exit status of the child.
void _dbus_babysitter_unref(DBusBabysitter *sitter)
Decrement the reference count on the babysitter object.
DBusBabysitter * _dbus_babysitter_ref(DBusBabysitter *sitter)
Increment the reference count on the babysitter object.
dbus_bool_t _dbus_babysitter_get_child_exited(DBusBabysitter *sitter)
Checks whether the child has exited, without blocking.
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.
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,...
char * _dbus_strdup(const char *str)
Duplicates a string.
void _dbus_babysitter_kill_child(DBusBabysitter *sitter)
Blocks until the babysitter process gives us the PID of the spawned grandchild, then kills the spawne...
dbus_bool_t _dbus_spawn_async_with_babysitter(DBusBabysitter **sitter_p, const char *log_name, char *const *argv, char *const *env, DBusSpawnFlags flags, DBusSpawnChildSetupFunc child_setup, void *user_data, DBusError *error)
Spawns a new process.
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
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:692
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:58
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:740
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:452
#define DBUS_ERROR_SPAWN_CHILD_EXITED
While starting a new process, the child exited with a status code.
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
#define DBUS_ERROR_SPAWN_FORK_FAILED
While starting a new process, the fork() call failed.
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:182
dbus_bool_t _dbus_string_append_strings(DBusString *str, char **strings, char separator)
Append vector with strings connected by separator.
Definition: dbus-string.c:1211
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
Definition: dbus-string.c:278
dbus_bool_t _dbus_string_append_byte(DBusString *str, unsigned char byte)
Appends a single byte to the string, returning FALSE if not enough memory.
Definition: dbus-string.c:1188
dbus_bool_t _dbus_socketpair(DBusSocket *fd1, DBusSocket *fd2, dbus_bool_t blocking, DBusError *error)
Creates pair of connect sockets (as in socketpair()).
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
dbus_bool_t _dbus_close_socket(DBusSocket fd, DBusError *error)
Closes a socket.
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
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
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
Definition: dbus-watch.c:232
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
Definition: dbus-watch.c:249
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
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
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 _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:414
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
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:324
Babysitter implementation details.
DBusWatch * sitter_watch
Sitter pipe watch.
DBusSocket socket_to_babysitter
Connection to the babysitter process.
unsigned int have_child_status
True if child status has been reaped.
char * log_name
the name under which to log messages about this process being spawned
int refcount
Reference count.
DBusWatchList * watches
Watches.
Object representing an exception.
Definition: dbus-errors.h:49
const char * message
public error message field
Definition: dbus-errors.h:51
Socket interface.
Definition: dbus-sysdeps.h:181
DBusWatchList implementation details.
Definition: dbus-watch.c:215
Implementation of DBusWatch.
Definition: dbus-watch.c:41