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

D-Bus 1.12.20

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
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
78 DBusWatchList *watches;
79 DBusWatch *sitter_watch;
80 DBusBabysitterFinishedFunc finished_cb;
81 void *finished_data;
82
83 dbus_bool_t have_spawn_errno;
84 int spawn_errno;
85 dbus_bool_t have_child_status;
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
151 DBusBabysitter *
152 _dbus_babysitter_ref (DBusBabysitter *sitter)
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);
173 _dbus_watch_list_remove_watch (sitter->watches, sitter->sitter_watch);
174 _dbus_watch_invalidate (sitter->sitter_watch);
175 _dbus_watch_unref (sitter->sitter_watch);
176 sitter->sitter_watch = NULL;
177 }
178
179 if (sitter->socket_to_babysitter.sock != INVALID_SOCKET)
180 {
181 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
182 sitter->socket_to_babysitter.sock = INVALID_SOCKET;
183 }
184 }
185
191 void
192 _dbus_babysitter_unref (DBusBabysitter *sitter)
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 {
245 _dbus_watch_invalidate (sitter->sitter_watch);
246 _dbus_watch_unref (sitter->sitter_watch);
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
273 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
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
288 dbus_bool_t
289 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
290 {
291 PING();
292 return (sitter->child_handle == NULL);
293 }
294
307 dbus_bool_t
308 _dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
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
332 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
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);
343 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
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();
351 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
352 "Process %s exited with status %d",
353 sitter->log_name, sitter->child_status);
354 }
355 else
356 {
357 PING();
358 dbus_set_error (error, DBUS_ERROR_FAILED,
359 "Process %s exited, status unknown",
360 sitter->log_name);
361 }
362 PING();
363 }
364
365 dbus_bool_t
366 _dbus_babysitter_set_watch_functions (DBusBabysitter *sitter,
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 static HANDLE
547 spawn_program (char* name, char** argv, char** envp)
548 {
549 PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
550 STARTUPINFOA si;
551 char *arg_string, *env_string;
552 BOOL result;
553
554 #ifdef DBUS_WINCE
555 if (argv && argv[0])
556 arg_string = build_commandline (argv + 1);
557 else
558 arg_string = NULL;
559 #else
560 arg_string = build_commandline (argv);
561 #endif
562 if (!arg_string)
563 return INVALID_HANDLE_VALUE;
564
565 env_string = build_env_string(envp);
566
567 memset (&si, 0, sizeof (si));
568 si.cb = sizeof (si);
569 #ifdef DBUS_WINCE
570 result = CreateProcessA (name, arg_string, NULL, NULL, FALSE, 0,
571 #else
572 result = CreateProcessA (NULL, arg_string, NULL, NULL, FALSE, 0,
573 #endif
574 (LPVOID)env_string, NULL, &si, &pi);
575 free (arg_string);
576 if (env_string)
577 free (env_string);
578
579 if (!result)
580 return INVALID_HANDLE_VALUE;
581
582 CloseHandle (pi.hThread);
583 return pi.hProcess;
584 }
585
586
587 static DWORD __stdcall
588 babysitter (void *parameter)
589 {
590 int ret = 0;
591 DBusBabysitter *sitter = (DBusBabysitter *) parameter;
592 HANDLE handle;
593
594 PING();
595 _dbus_verbose ("babysitter: spawning %s\n", sitter->log_name);
596
597 PING();
598 handle = spawn_program (sitter->log_name, sitter->argv, sitter->envp);
599
600 PING();
601 if (handle != INVALID_HANDLE_VALUE)
602 {
603 sitter->child_handle = handle;
604 }
605 else
606 {
607 sitter->child_handle = NULL;
608 sitter->have_spawn_errno = TRUE;
609 sitter->spawn_errno = GetLastError();
610 }
611
612 PING();
613 SetEvent (sitter->start_sync_event);
614
615 if (sitter->child_handle != NULL)
616 {
617 DWORD status;
618
619 PING();
620 // wait until process finished
621 WaitForSingleObject (sitter->child_handle, INFINITE);
622
623 PING();
624 ret = GetExitCodeProcess (sitter->child_handle, &status);
625 if (ret)
626 {
627 sitter->child_status = status;
628 sitter->have_child_status = TRUE;
629 }
630
631 CloseHandle (sitter->child_handle);
632 sitter->child_handle = NULL;
633 }
634
635 PING();
636 send (sitter->socket_to_main.sock, " ", 1, 0);
637
638 _dbus_babysitter_unref (sitter);
639
640 return ret ? 0 : 1;
641 }
642
643 dbus_bool_t
644 _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
645 const char *log_name,
646 char * const *argv,
647 char **envp,
648 DBusSpawnFlags flags _DBUS_GNUC_UNUSED,
649 DBusSpawnChildSetupFunc child_setup _DBUS_GNUC_UNUSED,
650 void *user_data _DBUS_GNUC_UNUSED,
651 DBusError *error)
652 {
653 DBusBabysitter *sitter;
654 DWORD sitter_thread_id;
655
656 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
657 _dbus_assert (argv[0] != NULL);
658
659 if (sitter_p != NULL)
660 *sitter_p = NULL;
661
662 PING();
663 sitter = _dbus_babysitter_new ();
664 if (sitter == NULL)
665 {
666 _DBUS_SET_OOM (error);
667 return FALSE;
668 }
669
670 sitter->log_name = _dbus_strdup (log_name);
671 if (sitter->log_name == NULL && log_name != NULL)
672 {
673 _DBUS_SET_OOM (error);
674 goto out0;
675 }
676
677 if (sitter->log_name == NULL)
678 sitter->log_name = _dbus_strdup (argv[0]);
679
680 if (sitter->log_name == NULL)
681 {
682 _DBUS_SET_OOM (error);
683 goto out0;
684 }
685
686 PING();
687 if (!_dbus_socketpair (&sitter->socket_to_babysitter,
688 &sitter->socket_to_main,
689 FALSE, error))
690 goto out0;
691
692 sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter,
693 DBUS_WATCH_READABLE,
694 TRUE, handle_watch, sitter, NULL);
695 PING();
696 if (sitter->sitter_watch == NULL)
697 {
698 _DBUS_SET_OOM (error);
699 goto out0;
700 }
701
702 PING();
703 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
704 {
705 /* we need to free it early so the destructor won't try to remove it
706 * without it having been added, which DBusLoop doesn't allow */
707 _dbus_watch_invalidate (sitter->sitter_watch);
708 _dbus_watch_unref (sitter->sitter_watch);
709 sitter->sitter_watch = NULL;
710
711 _DBUS_SET_OOM (error);
712 goto out0;
713 }
714
715 sitter->argc = protect_argv (argv, &sitter->argv);
716 if (sitter->argc == -1)
717 {
718 _DBUS_SET_OOM (error);
719 goto out0;
720 }
721 sitter->envp = envp;
722
723 PING();
724 sitter->thread_handle = (HANDLE) CreateThread (NULL, 0, babysitter,
725 _dbus_babysitter_ref (sitter), 0, &sitter_thread_id);
726
727 if (sitter->thread_handle == NULL)
728 {
729 PING();
730 dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
731 "Failed to create new thread");
732 goto out0;
733 }
734
735 PING();
736 WaitForSingleObject (sitter->start_sync_event, INFINITE);
737
738 PING();
739 if (sitter_p != NULL)
740 *sitter_p = sitter;
741 else
742 _dbus_babysitter_unref (sitter);
743
744 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
745
746 PING();
747 return TRUE;
748
749 out0:
750 _dbus_babysitter_unref (sitter);
751
752 return FALSE;
753 }
754
755 void
756 _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
757 DBusBabysitterFinishedFunc finished,
758 void *user_data)
759 {
760 sitter->finished_cb = finished;
761 sitter->finished_data = user_data;
762 }
763
764 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
765
766 void
767 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
768 {
769 /* The thread terminates after the child does. We want to wait for the thread,
770 * not just the child, to avoid data races and ensure that it has freed all
771 * its memory. */
772 WaitForSingleObject (sitter->thread_handle, INFINITE);
773 }
_dbus_babysitter_ref
DBusBabysitter * _dbus_babysitter_ref(DBusBabysitter *sitter)
Increment the reference count on the babysitter object.
Definition: dbus-spawn.c:307
_dbus_atomic_dec
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
Definition: dbus-sysdeps-unix.c:2866
_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:382
_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.c:721
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:415
_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.c:770
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-win.c:67
DBusWatch
Implementation of DBusWatch.
Definition: dbus-watch.c:41
_dbus_spawn_async_with_babysitter
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.
Definition: dbus-spawn.c:1249
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:420
_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.c:828
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:355
DBUS_ERROR_SPAWN_EXEC_FAILED
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
Definition: dbus-protocol.h:416
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:702
dbus_malloc
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:462
DBusSocket
Socket interface.
Definition: dbus-sysdeps.h:175
DBusBabysitter
Babysitter implementation details.
Definition: dbus-spawn-win.c:62
FALSE
#define FALSE
_dbus_assert_not_reached
#define _dbus_assert_not_reached(explanation)
Definition: dbus-internals.h:163
DBusBabysitter::watches
DBusWatchList * watches
Watches.
Definition: dbus-spawn-win.c:78
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:418
DBusAtomic
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:307
_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:152
_dbus_babysitter_unref
void _dbus_babysitter_unref(DBusBabysitter *sitter)
Decrement the reference count on the babysitter object.
Definition: dbus-spawn.c:329
_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:3460
_dbus_strdup
char * _dbus_strdup(const char *str)
Duplicates a string.
Definition: dbus-internals.c:536
_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_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:296
DBusBabysitter::socket_to_babysitter
DBusSocket socket_to_babysitter
Connection to the babysitter process.
Definition: dbus-spawn-win.c:75
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
DBusBabysitter::sitter_watch
DBusWatch * sitter_watch
Sitter pipe watch.
Definition: dbus-spawn-win.c:79
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:2843
_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.c:699
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.c:746
dbus_bool_t
dbus_uint32_t dbus_bool_t
Definition: dbus-types.h:35
NULL
#define NULL