D-Bus: dbus-spawn-win.c Source File

D-Bus 1.13.18

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 {
63 DBusAtomic refcount;
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
71 DBusWatchList *watches;
72 DBusWatch *sitter_watch;
73 DBusBabysitterFinishedFunc finished_cb;
74 void *finished_data;
75
76 dbus_bool_t have_spawn_errno;
77 int spawn_errno;
78 dbus_bool_t have_child_status;
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, __FUNCTION__);
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
133 DBusBabysitter *
134 _dbus_babysitter_ref (DBusBabysitter *sitter)
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, __FUNCTION__);
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);
155 _dbus_watch_list_remove_watch (sitter->watches, sitter->sitter_watch);
156 _dbus_watch_invalidate (sitter->sitter_watch);
157 _dbus_watch_unref (sitter->sitter_watch);
158 sitter->sitter_watch = NULL;
159 }
160
161 if (sitter->socket_to_babysitter.sock != INVALID_SOCKET)
162 {
163 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
164 sitter->socket_to_babysitter.sock = INVALID_SOCKET;
165 }
166 }
167
173 void
174 _dbus_babysitter_unref (DBusBabysitter *sitter)
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, __FUNCTION__);
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 {
203 _dbus_watch_invalidate (sitter->sitter_watch);
204 _dbus_watch_unref (sitter->sitter_watch);
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
224 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
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
239 dbus_bool_t
240 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
241 {
242 PING();
243 return (sitter->child_handle == NULL);
244 }
245
258 dbus_bool_t
259 _dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
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
283 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
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);
294 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
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();
302 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
303 "Process %s exited with status %d",
304 sitter->log_name, sitter->child_status);
305 }
306 else
307 {
308 PING();
309 dbus_set_error (error, DBUS_ERROR_FAILED,
310 "Process %s exited, status unknown",
311 sitter->log_name);
312 }
313 PING();
314 }
315
316 dbus_bool_t
317 _dbus_babysitter_set_watch_functions (DBusBabysitter *sitter,
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
372 while (argv[argc])
373 ++argc;
374 *new_argv = dbus_malloc ((argc + 1) * sizeof (char *));
375 if (*new_argv == NULL)
376 return -1;
377
378 for (i = 0; i < argc; i++)
379 (*new_argv)[i] = NULL;
380
381 /* Quote each argv element if necessary, so that it will get
382 * reconstructed correctly in the C runtime startup code. Note that
383 * the unquoting algorithm in the C runtime is really weird, and
384 * rather different than what Unix shells do. See stdargv.c in the C
385 * runtime sources (in the Platform SDK, in src/crt).
386 *
387 * Note that an new_argv[0] constructed by this function should
388 * *not* be passed as the filename argument to a spawn* or exec*
389 * family function. That argument should be the real file name
390 * without any quoting.
391 */
392 for (i = 0; i < argc; i++)
393 {
394 const char *p = argv[i];
395 char *q;
396 int len = 0;
397 int need_dblquotes = FALSE;
398 while (*p)
399 {
400 if (*p == ' ' || *p == '\t')
401 need_dblquotes = TRUE;
402 else if (*p == '"')
403 len++;
404 else if (*p == '\\')
405 {
406 const char *pp = p;
407 while (*pp && *pp == '\\')
408 pp++;
409 if (*pp == '"')
410 len++;
411 }
412 len++;
413 p++;
414 }
415
416 q = (*new_argv)[i] = dbus_malloc (len + need_dblquotes*2 + 1);
417
418 if (q == NULL)
419 return -1;
420
421
422 p = argv[i];
423
424 if (need_dblquotes)
425 *q++ = '"';
426
427 while (*p)
428 {
429 if (*p == '"')
430 *q++ = '\\';
431 else if (*p == '\\')
432 {
433 const char *pp = p;
434 while (*pp && *pp == '\\')
435 pp++;
436 if (*pp == '"')
437 *q++ = '\\';
438 }
439 *q++ = *p;
440 p++;
441 }
442
443 if (need_dblquotes)
444 *q++ = '"';
445 *q++ = '\0';
446 /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (*new_argv)[i]); */
447 }
448 (*new_argv)[argc] = NULL;
449
450 return argc;
451 }
452
453
454 /* From GPGME, relicensed by g10 Code GmbH. */
455 static char *
456 compose_string (char **strings, char separator)
457 {
458 int i;
459 int n = 0;
460 char *buf;
461 char *p;
462
463 if (!strings || !strings[0])
464 return 0;
465 for (i = 0; strings[i]; i++)
466 n += strlen (strings[i]) + 1;
467 n++;
468
469 buf = p = malloc (n);
470 if (!buf)
471 return NULL;
472 for (i = 0; strings[i]; i++)
473 {
474 strcpy (p, strings[i]);
475 p += strlen (strings[i]);
476 *(p++) = separator;
477 }
478 p--;
479 *(p++) = '\0';
480 *p = '\0';
481
482 return buf;
483 }
484
485 static char *
486 build_commandline (char **argv)
487 {
488 return compose_string (argv, ' ');
489 }
490
491 static char *
492 build_env_string (char** envp)
493 {
494 return compose_string (envp, '\0');
495 }
496
497 HANDLE
498 _dbus_spawn_program (const char *name,
499 char **argv,
500 char **envp)
501 {
502 PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
503 STARTUPINFOA si;
504 char *arg_string, *env_string;
505 BOOL result;
506
507 #ifdef DBUS_WINCE
508 if (argv && argv[0])
509 arg_string = build_commandline (argv + 1);
510 else
511 arg_string = NULL;
512 #else
513 arg_string = build_commandline (argv);
514 #endif
515 if (!arg_string)
516 return INVALID_HANDLE_VALUE;
517
518 env_string = build_env_string(envp);
519
520 memset (&si, 0, sizeof (si));
521 si.cb = sizeof (si);
522
523 #ifdef DBUS_ENABLE_VERBOSE_MODE
524 {
525 char *s = compose_string (envp, ';');
526 _dbus_verbose ("spawning '%s'' with args: '%s' env: '%s'\n", name, arg_string, s);
527 free (s);
528 }
529 #endif
530
531 #ifdef DBUS_WINCE
532 result = CreateProcessA (name, arg_string, NULL, NULL, FALSE, 0,
533 #else
534 result = CreateProcessA (NULL, arg_string, NULL, NULL, FALSE, 0,
535 #endif
536 (LPVOID)env_string, NULL, &si, &pi);
537 free (arg_string);
538 if (env_string)
539 free (env_string);
540
541 if (!result)
542 return INVALID_HANDLE_VALUE;
543
544 CloseHandle (pi.hThread);
545 return pi.hProcess;
546 }
547
548
549 static DWORD __stdcall
550 babysitter (void *parameter)
551 {
552 int ret = 0;
553 DBusBabysitter *sitter = (DBusBabysitter *) parameter;
554
555 PING();
556 if (sitter->child_handle != NULL)
557 {
558 DWORD status;
559
560 PING();
561 // wait until process finished
562 WaitForSingleObject (sitter->child_handle, INFINITE);
563
564 PING();
565 ret = GetExitCodeProcess (sitter->child_handle, &status);
566 if (ret)
567 {
568 sitter->child_status = status;
569 sitter->have_child_status = TRUE;
570 }
571
572 CloseHandle (sitter->child_handle);
573 sitter->child_handle = NULL;
574 }
575
576 PING();
577 send (sitter->socket_to_main.sock, " ", 1, 0);
578
579 _dbus_babysitter_unref (sitter);
580
581 return ret ? 0 : 1;
582 }
583
584 dbus_bool_t
585 _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
586 const char *log_name,
587 char * const *argv,
588 char * const *envp,
589 DBusSpawnFlags flags _DBUS_GNUC_UNUSED,
590 DBusSpawnChildSetupFunc child_setup _DBUS_GNUC_UNUSED,
591 void *user_data _DBUS_GNUC_UNUSED,
592 DBusError *error)
593 {
594 DBusBabysitter *sitter;
595 DWORD sitter_thread_id;
596 HANDLE handle;
597 int argc;
598 char **my_argv = NULL;
599
600 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
601 _dbus_assert (argv[0] != NULL);
602
603 if (sitter_p != NULL)
604 *sitter_p = NULL;
605
606 PING();
607 sitter = _dbus_babysitter_new ();
608 if (sitter == NULL)
609 {
610 _DBUS_SET_OOM (error);
611 return FALSE;
612 }
613
614 sitter->log_name = _dbus_strdup (log_name);
615 if (sitter->log_name == NULL && log_name != NULL)
616 {
617 _DBUS_SET_OOM (error);
618 goto out0;
619 }
620
621 if (sitter->log_name == NULL)
622 sitter->log_name = _dbus_strdup (argv[0]);
623
624 if (sitter->log_name == NULL)
625 {
626 _DBUS_SET_OOM (error);
627 goto out0;
628 }
629
630 PING();
631 if (!_dbus_socketpair (&sitter->socket_to_babysitter,
632 &sitter->socket_to_main,
633 FALSE, error))
634 goto out0;
635
636 sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter,
637 DBUS_WATCH_READABLE,
638 TRUE, handle_watch, sitter, NULL);
639 PING();
640 if (sitter->sitter_watch == NULL)
641 {
642 _DBUS_SET_OOM (error);
643 goto out0;
644 }
645
646 PING();
647 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
648 {
649 /* we need to free it early so the destructor won't try to remove it
650 * without it having been added, which DBusLoop doesn't allow */
651 _dbus_watch_invalidate (sitter->sitter_watch);
652 _dbus_watch_unref (sitter->sitter_watch);
653 sitter->sitter_watch = NULL;
654
655 _DBUS_SET_OOM (error);
656 goto out0;
657 }
658
659 argc = protect_argv (argv, &my_argv);
660 if (argc == -1)
661 {
662 _DBUS_SET_OOM (error);
663 goto out0;
664 }
665
666 _dbus_verbose ("babysitter: spawn child '%s'\n", my_argv[0]);
667
668 PING();
669 handle = _dbus_spawn_program (sitter->log_name, my_argv, (char **) envp);
670
671 if (my_argv != NULL)
672 {
673 dbus_free_string_array (my_argv);
674 }
675
676 PING();
677 if (handle == INVALID_HANDLE_VALUE)
678 {
679 sitter->child_handle = NULL;
680 sitter->have_spawn_errno = TRUE;
681 sitter->spawn_errno = GetLastError();
682 dbus_set_error_const (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
683 "Failed to spawn child");
684 goto out0;
685 }
686
687 sitter->child_handle = handle;
688
689 PING();
690 sitter->thread_handle = (HANDLE) CreateThread (NULL, 0, babysitter,
691 _dbus_babysitter_ref (sitter), 0, &sitter_thread_id);
692
693 if (sitter->thread_handle == NULL)
694 {
695 PING();
696 dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
697 "Failed to create new thread");
698 goto out0;
699 }
700
701 PING();
702 if (sitter_p != NULL)
703 *sitter_p = sitter;
704 else
705 _dbus_babysitter_unref (sitter);
706
707 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
708
709 PING();
710 return TRUE;
711
712 out0:
713 _dbus_babysitter_unref (sitter);
714
715 return FALSE;
716 }
717
718 void
719 _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
720 DBusBabysitterFinishedFunc finished,
721 void *user_data)
722 {
723 sitter->finished_cb = finished;
724 sitter->finished_data = user_data;
725 }
726
727 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
728
729 void
730 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
731 {
732 /* The thread terminates after the child does. We want to wait for the thread,
733 * not just the child, to avoid data races and ensure that it has freed all
734 * its memory. */
735 WaitForSingleObject (sitter->thread_handle, INFINITE);
736 }
_dbus_babysitter_ref
DBusBabysitter * _dbus_babysitter_ref(DBusBabysitter *sitter)
Increment the reference count on the babysitter object.
Definition: dbus-spawn-win.c:134
_dbus_atomic_dec
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
Definition: dbus-sysdeps-unix.c:3057
_dbus_watch_list_add_watch
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_watch_list_new
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
Definition: dbus-watch.c:232
_dbus_babysitter_get_child_exited
dbus_bool_t _dbus_babysitter_get_child_exited(DBusBabysitter *sitter)
Checks whether the child has exited, without blocking.
Definition: dbus-spawn-win.c:240
DBusBabysitter::have_child_status
unsigned int have_child_status
True if child status has been reaped.
Definition: dbus-spawn-unix.c:272
dbus_set_error_const
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_watch_list_remove_watch
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
_dbus_babysitter_set_child_exit_error
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-win.c:283
DBusFreeFunction
void(* DBusFreeFunction)(void *memory)
Definition: dbus-memory.h:63
DBusBabysitter::log_name
char * log_name
the name under which to log messages about this process being spawned
Definition: dbus-spawn-unix.c:253
DBusWatch
Implementation of DBusWatch.
Definition: dbus-watch.c:41
DBUS_ERROR_SPAWN_CHILD_EXITED
#define DBUS_ERROR_SPAWN_CHILD_EXITED
While starting a new process, the child exited with a status code.
Definition: dbus-protocol.h:424
_dbus_babysitter_set_watch_functions
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-win.c:317
dbus_int32_t
int dbus_int32_t
Definition: dbus-arch-deps.h:42
TRUE
#define TRUE
DBUS_WATCH_READABLE
@ DBUS_WATCH_READABLE
As in POLLIN.
Definition: dbus-connection.h:61
DBUS_ERROR_FAILED
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
Definition: dbus-protocol.h:359
DBUS_ERROR_SPAWN_EXEC_FAILED
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
Definition: dbus-protocol.h:420
DBusAddWatchFunction
dbus_bool_t(* DBusAddWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus needs a new watch to be monitored by the main loop.
Definition: dbus-connection.h:92
_dbus_watch_unref
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
dbus_free
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:704
dbus_malloc
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:464
DBusSocket
Socket interface.
Definition: dbus-sysdeps.h:181
DBusBabysitter
Babysitter implementation details.
Definition: dbus-spawn-unix.c:250
FALSE
#define FALSE
_dbus_assert_not_reached
#define _dbus_assert_not_reached(explanation)
Definition: dbus-internals.h:164
DBusBabysitter::watches
DBusWatchList * watches
Watches.
Definition: dbus-spawn-unix.c:262
DBusWatchList
DBusWatchList implementation details.
Definition: dbus-watch.c:215
DBUS_ERROR_SPAWN_FORK_FAILED
#define DBUS_ERROR_SPAWN_FORK_FAILED
While starting a new process, the fork() call failed.
Definition: dbus-protocol.h:422
DBusAtomic
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:327
_dbus_close_socket
dbus_bool_t _dbus_close_socket(DBusSocket fd, DBusError *error)
Closes a socket.
Definition: dbus-sysdeps-unix.c:286
DBusWatchToggledFunction
void(* DBusWatchToggledFunction)(DBusWatch *watch, void *data)
Called when dbus_watch_get_enabled() may return a different value than it did before.
Definition: dbus-connection.h:98
_dbus_assert
#define _dbus_assert(condition)
Definition: dbus-internals.h:153
_dbus_babysitter_unref
void _dbus_babysitter_unref(DBusBabysitter *sitter)
Decrement the reference count on the babysitter object.
Definition: dbus-spawn-win.c:174
_dbus_socketpair
dbus_bool_t _dbus_socketpair(DBusSocket *fd1, DBusSocket *fd2, dbus_bool_t blocking, DBusError *error)
Creates pair of connect sockets (as in socketpair()).
Definition: dbus-sysdeps-unix.c:3723
_dbus_strdup
char * _dbus_strdup(const char *str)
Duplicates a string.
Definition: dbus-internals.c:589
_dbus_watch_list_free
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
Definition: dbus-watch.c:249
DBusError
Object representing an exception.
Definition: dbus-errors.h:49
_dbus_spawn_async_with_babysitter
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.
Definition: dbus-spawn-unix.c:1271
_dbus_watch_invalidate
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_watch_list_set_functions
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
DBusBabysitter::socket_to_babysitter
DBusSocket socket_to_babysitter
Connection to the babysitter process.
Definition: dbus-spawn-unix.c:256
dbus_set_error
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
dbus_free_string_array
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:752
DBusBabysitter::sitter_watch
DBusWatch * sitter_watch
Sitter pipe watch.
Definition: dbus-spawn-unix.c:265
DBusRemoveWatchFunction
void(* DBusRemoveWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus no longer needs a watch to be monitored by the main loop.
Definition: dbus-connection.h:104
_dbus_atomic_inc
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
Definition: dbus-sysdeps-unix.c:3034
DBusBabysitter::refcount
int refcount
Reference count.
Definition: dbus-spawn-unix.c:251
_dbus_babysitter_kill_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...
Definition: dbus-spawn-win.c:224
dbus_new0
#define dbus_new0(type, count)
Definition: dbus-memory.h:58
_dbus_watch_new
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
_dbus_babysitter_get_child_exit_status
dbus_bool_t _dbus_babysitter_get_child_exit_status(DBusBabysitter *sitter, int *status)
Gets the exit status of the child.
Definition: dbus-spawn-win.c:259
dbus_bool_t
dbus_uint32_t dbus_bool_t
Definition: dbus-types.h:35
NULL
#define NULL