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
61struct 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
82static 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
96static 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
147static void
148close_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
173void
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)
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
223void
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{
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
282void
284 DBusError *error)
285{
286 PING();
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();
326 add_function,
327 remove_function,
328 toggled_function,
329 data,
330 free_data_function);
331}
332
333static dbus_bool_t
334handle_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
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 */
365static int
366protect_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 {
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
457static dbus_bool_t
458build_commandline (char **argv, DBusString *result)
459{
460 return _dbus_string_append_strings (result, argv, ' ');
461}
462
463static dbus_bool_t
464build_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
489HANDLE
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
585out:
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
601static DWORD __stdcall
602babysitter (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();
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
778out0:
779 _dbus_babysitter_unref (sitter);
780
781 return FALSE;
782}
783
784void
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
795void
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.
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.
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,...
void _dbus_babysitter_kill_child(DBusBabysitter *sitter)
Blocks until the babysitter process gives us the PID of the spawned grandchild, then kills the spawne...
DBusBabysitter * _dbus_babysitter_ref(DBusBabysitter *sitter)
Increment the reference count on the babysitter object.
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