5 #if !defined(SPAWN_DEBUG) || defined(_MSC_VER)
8 #define PING() fprintf (stderr, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__); fflush (stderr)
13 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
14 /* dbus-spawn-win32.c Wrapper around g_spawn
16 * Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
17 * Copyright (C) 2003 CodeFactory AB
18 * Copyright (C) 2005 Novell, Inc.
20 * Licensed under the Academic Free License version 2.1
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.
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.
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
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"
44 #define WIN32_LEAN_AND_MEAN
47 //#include <windows.h>
59 * Babysitter implementation details
65 HANDLE start_sync_event;
75 DBusSocket socket_to_babysitter; /* Connection to the babysitter thread */
76 DBusSocket socket_to_main;
78 DBusWatchList *watches;
79 DBusWatch *sitter_watch;
80 DBusBabysitterFinishedFunc finished_cb;
83 dbus_bool_t have_spawn_errno;
85 dbus_bool_t have_child_status;
90 _dbus_babysitter_trace_ref (DBusBabysitter *sitter,
95 #ifdef DBUS_ENABLE_VERBOSE_MODE
96 static int enabled = -1;
98 _dbus_trace_ref ("DBusBabysitter", sitter, old_refcount, new_refcount, why,
99 "DBUS_BABYSITTER_TRACE", &enabled);
103 static DBusBabysitter*
104 _dbus_babysitter_new (void)
106 DBusBabysitter *sitter;
107 dbus_int32_t old_refcount;
109 sitter = dbus_new0 (DBusBabysitter, 1);
113 old_refcount = _dbus_atomic_inc (&sitter->refcount);
115 _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, __FUNCTION__);
117 sitter->start_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
118 if (sitter->start_sync_event == NULL)
120 _dbus_babysitter_unref (sitter);
124 sitter->child_handle = NULL;
126 sitter->socket_to_babysitter = sitter->socket_to_main = _dbus_socket_get_invalid ();
132 sitter->watches = _dbus_watch_list_new ();
133 if (sitter->watches == NULL)
135 _dbus_babysitter_unref (sitter);
139 sitter->have_spawn_errno = FALSE;
140 sitter->have_child_status = FALSE;
146 * Increment the reference count on the babysitter object.
148 * @param sitter the babysitter
149 * @returns the babysitter
152 _dbus_babysitter_ref (DBusBabysitter *sitter)
154 dbus_int32_t old_refcount;
156 _dbus_assert (sitter != NULL);
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__);
166 close_socket_to_babysitter (DBusBabysitter *sitter)
168 _dbus_verbose ("Closing babysitter\n");
170 if (sitter->sitter_watch != NULL)
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;
179 if (sitter->socket_to_babysitter.sock != INVALID_SOCKET)
181 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
182 sitter->socket_to_babysitter.sock = INVALID_SOCKET;
187 * Decrement the reference count on the babysitter object.
189 * @param sitter the babysitter
192 _dbus_babysitter_unref (DBusBabysitter *sitter)
195 dbus_int32_t old_refcount;
198 _dbus_assert (sitter != NULL);
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__);
204 if (old_refcount == 1)
206 close_socket_to_babysitter (sitter);
208 if (sitter->socket_to_main.sock != INVALID_SOCKET)
210 _dbus_close_socket (sitter->socket_to_main, NULL);
211 sitter->socket_to_main.sock = INVALID_SOCKET;
215 if (sitter->argv != NULL)
217 for (i = 0; i < sitter->argc; i++)
218 if (sitter->argv[i] != NULL)
220 dbus_free (sitter->argv[i]);
221 sitter->argv[i] = NULL;
223 dbus_free (sitter->argv);
227 if (sitter->envp != NULL)
229 char **e = sitter->envp;
233 dbus_free (sitter->envp);
237 if (sitter->child_handle != NULL)
239 CloseHandle (sitter->child_handle);
240 sitter->child_handle = NULL;
243 if (sitter->sitter_watch)
245 _dbus_watch_invalidate (sitter->sitter_watch);
246 _dbus_watch_unref (sitter->sitter_watch);
247 sitter->sitter_watch = NULL;
251 _dbus_watch_list_free (sitter->watches);
253 if (sitter->start_sync_event != NULL)
256 CloseHandle (sitter->start_sync_event);
257 sitter->start_sync_event = NULL;
260 if (sitter->thread_handle)
262 CloseHandle (sitter->thread_handle);
263 sitter->thread_handle = NULL;
266 dbus_free (sitter->log_name);
273 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
276 if (sitter->child_handle == NULL)
277 return; /* child is already dead, or we're so hosed we'll never recover */
280 TerminateProcess (sitter->child_handle, 12345);
284 * Checks whether the child has exited, without blocking.
286 * @param sitter the babysitter
289 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
292 return (sitter->child_handle == NULL);
296 * Gets the exit status of the child. We do this so implementation specific
297 * detail is not cluttering up dbus, for example the system launcher code.
298 * This can only be called if the child has exited, i.e. call
299 * _dbus_babysitter_get_child_exited(). It returns FALSE if the child
300 * did not return a status code, e.g. because the child was signaled
301 * or we failed to ever launch the child in the first place.
303 * @param sitter the babysitter
304 * @param status the returned status code
305 * @returns #FALSE on failure
308 _dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
311 if (!_dbus_babysitter_get_child_exited (sitter))
312 _dbus_assert_not_reached ("Child has not exited");
314 if (!sitter->have_child_status ||
315 sitter->child_status == STILL_ACTIVE)
318 *status = sitter->child_status;
323 * Sets the #DBusError with an explanation of why the spawned
324 * child process exited (on a signal, or whatever). If
325 * the child process has not exited, does nothing (error
326 * will remain unset).
328 * @param sitter the babysitter
329 * @param error an error to fill in
332 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
336 if (!_dbus_babysitter_get_child_exited (sitter))
340 if (sitter->have_spawn_errno)
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);
348 else if (sitter->have_child_status)
351 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
352 "Process %s exited with status %d",
353 sitter->log_name, sitter->child_status);
358 dbus_set_error (error, DBUS_ERROR_FAILED,
359 "Process %s exited, status unknown",
366 _dbus_babysitter_set_watch_functions (DBusBabysitter *sitter,
367 DBusAddWatchFunction add_function,
368 DBusRemoveWatchFunction remove_function,
369 DBusWatchToggledFunction toggled_function,
371 DBusFreeFunction free_data_function)
374 return _dbus_watch_list_set_functions (sitter->watches,
383 handle_watch (DBusWatch *watch,
384 unsigned int condition,
387 DBusBabysitter *sitter = data;
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
400 close_socket_to_babysitter (sitter);
403 if (_dbus_babysitter_get_child_exited (sitter) &&
404 sitter->finished_cb != NULL)
406 sitter->finished_cb (sitter, sitter->finished_data);
407 sitter->finished_cb = NULL;
413 /* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
415 protect_argv (char * const *argv,
423 *new_argv = dbus_malloc ((argc + 1) * sizeof (char *));
424 if (*new_argv == NULL)
427 for (i = 0; i < argc; i++)
428 (*new_argv)[i] = NULL;
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).
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.
441 for (i = 0; i < argc; i++)
443 const char *p = argv[i];
446 int need_dblquotes = FALSE;
449 if (*p == ' ' || *p == '\t')
450 need_dblquotes = TRUE;
456 while (*pp && *pp == '\\')
465 q = (*new_argv)[i] = dbus_malloc (len + need_dblquotes*2 + 1);
483 while (*pp && *pp == '\\')
495 /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (*new_argv)[i]); */
497 (*new_argv)[argc] = NULL;
503 /* From GPGME, relicensed by g10 Code GmbH. */
505 compose_string (char **strings, char separator)
512 if (!strings || !strings[0])
514 for (i = 0; strings[i]; i++)
515 n += strlen (strings[i]) + 1;
518 buf = p = malloc (n);
521 for (i = 0; strings[i]; i++)
523 strcpy (p, strings[i]);
524 p += strlen (strings[i]);
535 build_commandline (char **argv)
537 return compose_string (argv, ' ');
541 build_env_string (char** envp)
543 return compose_string (envp, '\0');
547 spawn_program (char* name, char** argv, char** envp)
549 PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
551 char *arg_string, *env_string;
556 arg_string = build_commandline (argv + 1);
560 arg_string = build_commandline (argv);
563 return INVALID_HANDLE_VALUE;
565 env_string = build_env_string(envp);
567 memset (&si, 0, sizeof (si));
570 result = CreateProcessA (name, arg_string, NULL, NULL, FALSE, 0,
572 result = CreateProcessA (NULL, arg_string, NULL, NULL, FALSE, 0,
574 (LPVOID)env_string, NULL, &si, &pi);
580 return INVALID_HANDLE_VALUE;
582 CloseHandle (pi.hThread);
587 static DWORD __stdcall
588 babysitter (void *parameter)
591 DBusBabysitter *sitter = (DBusBabysitter *) parameter;
595 _dbus_verbose ("babysitter: spawning %s\n", sitter->log_name);
598 handle = spawn_program (sitter->log_name, sitter->argv, sitter->envp);
601 if (handle != INVALID_HANDLE_VALUE)
603 sitter->child_handle = handle;
607 sitter->child_handle = NULL;
608 sitter->have_spawn_errno = TRUE;
609 sitter->spawn_errno = GetLastError();
613 SetEvent (sitter->start_sync_event);
615 if (sitter->child_handle != NULL)
620 // wait until process finished
621 WaitForSingleObject (sitter->child_handle, INFINITE);
624 ret = GetExitCodeProcess (sitter->child_handle, &status);
627 sitter->child_status = status;
628 sitter->have_child_status = TRUE;
631 CloseHandle (sitter->child_handle);
632 sitter->child_handle = NULL;
636 send (sitter->socket_to_main.sock, " ", 1, 0);
638 _dbus_babysitter_unref (sitter);
644 _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
645 const char *log_name,
648 DBusSpawnFlags flags _DBUS_GNUC_UNUSED,
649 DBusSpawnChildSetupFunc child_setup _DBUS_GNUC_UNUSED,
650 void *user_data _DBUS_GNUC_UNUSED,
653 DBusBabysitter *sitter;
654 DWORD sitter_thread_id;
656 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
657 _dbus_assert (argv[0] != NULL);
659 if (sitter_p != NULL)
663 sitter = _dbus_babysitter_new ();
666 _DBUS_SET_OOM (error);
670 sitter->log_name = _dbus_strdup (log_name);
671 if (sitter->log_name == NULL && log_name != NULL)
673 _DBUS_SET_OOM (error);
677 if (sitter->log_name == NULL)
678 sitter->log_name = _dbus_strdup (argv[0]);
680 if (sitter->log_name == NULL)
682 _DBUS_SET_OOM (error);
687 if (!_dbus_socketpair (&sitter->socket_to_babysitter,
688 &sitter->socket_to_main,
692 sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter,
694 TRUE, handle_watch, sitter, NULL);
696 if (sitter->sitter_watch == NULL)
698 _DBUS_SET_OOM (error);
703 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
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;
711 _DBUS_SET_OOM (error);
715 sitter->argc = protect_argv (argv, &sitter->argv);
716 if (sitter->argc == -1)
718 _DBUS_SET_OOM (error);
724 sitter->thread_handle = (HANDLE) CreateThread (NULL, 0, babysitter,
725 _dbus_babysitter_ref (sitter), 0, &sitter_thread_id);
727 if (sitter->thread_handle == NULL)
730 dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
731 "Failed to create new thread");
736 WaitForSingleObject (sitter->start_sync_event, INFINITE);
739 if (sitter_p != NULL)
742 _dbus_babysitter_unref (sitter);
744 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
750 _dbus_babysitter_unref (sitter);
756 _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
757 DBusBabysitterFinishedFunc finished,
760 sitter->finished_cb = finished;
761 sitter->finished_data = user_data;
764 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
767 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
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
772 WaitForSingleObject (sitter->thread_handle, INFINITE);