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
46 //#include <windows.h>
58 * Babysitter implementation details
64 HANDLE start_sync_event;
65 #ifdef DBUS_BUILD_TESTS
67 HANDLE end_sync_event;
71 DBusSpawnChildSetupFunc child_setup;
79 int socket_to_babysitter; /* Connection to the babysitter thread */
82 DBusWatchList *watches;
83 DBusWatch *sitter_watch;
85 dbus_bool_t have_spawn_errno;
87 dbus_bool_t have_child_status;
91 static DBusBabysitter*
92 _dbus_babysitter_new (void)
94 DBusBabysitter *sitter;
96 sitter = dbus_new0 (DBusBabysitter, 1);
100 sitter->refcount = 1;
102 sitter->start_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
103 if (sitter->start_sync_event == NULL)
105 _dbus_babysitter_unref (sitter);
109 #ifdef DBUS_BUILD_TESTS
110 sitter->end_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
111 if (sitter->end_sync_event == NULL)
113 _dbus_babysitter_unref (sitter);
118 sitter->child_handle = NULL;
120 sitter->socket_to_babysitter = sitter->socket_to_main = -1;
126 sitter->watches = _dbus_watch_list_new ();
127 if (sitter->watches == NULL)
129 _dbus_babysitter_unref (sitter);
133 sitter->have_spawn_errno = FALSE;
134 sitter->have_child_status = FALSE;
140 * Increment the reference count on the babysitter object.
142 * @param sitter the babysitter
143 * @returns the babysitter
146 _dbus_babysitter_ref (DBusBabysitter *sitter)
149 _dbus_assert (sitter != NULL);
150 _dbus_assert (sitter->refcount > 0);
152 sitter->refcount += 1;
158 * Decrement the reference count on the babysitter object.
160 * @param sitter the babysitter
163 _dbus_babysitter_unref (DBusBabysitter *sitter)
168 _dbus_assert (sitter != NULL);
169 _dbus_assert (sitter->refcount > 0);
171 sitter->refcount -= 1;
173 if (sitter->refcount == 0)
175 if (sitter->socket_to_babysitter != -1)
177 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
178 sitter->socket_to_babysitter = -1;
181 if (sitter->socket_to_main != -1)
183 _dbus_close_socket (sitter->socket_to_main, NULL);
184 sitter->socket_to_main = -1;
188 if (sitter->argv != NULL)
190 for (i = 0; i < sitter->argc; i++)
191 if (sitter->argv[i] != NULL)
193 dbus_free (sitter->argv[i]);
194 sitter->argv[i] = NULL;
196 dbus_free (sitter->argv);
200 if (sitter->envp != NULL)
202 char **e = sitter->envp;
206 dbus_free (sitter->envp);
210 if (sitter->child_handle != NULL)
212 CloseHandle (sitter->child_handle);
213 sitter->child_handle = NULL;
216 if (sitter->sitter_watch)
218 _dbus_watch_invalidate (sitter->sitter_watch);
219 _dbus_watch_unref (sitter->sitter_watch);
220 sitter->sitter_watch = NULL;
224 _dbus_watch_list_free (sitter->watches);
226 if (sitter->start_sync_event != NULL)
229 CloseHandle (sitter->start_sync_event);
230 sitter->start_sync_event = NULL;
233 #ifdef DBUS_BUILD_TESTS
234 if (sitter->end_sync_event != NULL)
236 CloseHandle (sitter->end_sync_event);
237 sitter->end_sync_event = NULL;
241 dbus_free (sitter->executable);
248 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
251 if (sitter->child_handle == NULL)
252 return; /* child is already dead, or we're so hosed we'll never recover */
255 TerminateProcess (sitter->child_handle, 12345);
259 * Checks whether the child has exited, without blocking.
261 * @param sitter the babysitter
264 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
267 return (sitter->child_handle == NULL);
271 * Gets the exit status of the child. We do this so implementation specific
272 * detail is not cluttering up dbus, for example the system launcher code.
273 * This can only be called if the child has exited, i.e. call
274 * _dbus_babysitter_get_child_exited(). It returns FALSE if the child
275 * did not return a status code, e.g. because the child was signaled
276 * or we failed to ever launch the child in the first place.
278 * @param sitter the babysitter
279 * @param status the returned status code
280 * @returns #FALSE on failure
283 _dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
286 if (!_dbus_babysitter_get_child_exited (sitter))
287 _dbus_assert_not_reached ("Child has not exited");
289 if (!sitter->have_child_status ||
290 sitter->child_status == STILL_ACTIVE)
293 *status = sitter->child_status;
298 * Sets the #DBusError with an explanation of why the spawned
299 * child process exited (on a signal, or whatever). If
300 * the child process has not exited, does nothing (error
301 * will remain unset).
303 * @param sitter the babysitter
304 * @param error an error to fill in
307 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
311 if (!_dbus_babysitter_get_child_exited (sitter))
315 if (sitter->have_spawn_errno)
317 char *emsg = _dbus_win_error_string (sitter->spawn_errno);
318 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
319 "Failed to execute program %s: %s",
320 sitter->executable, emsg);
321 _dbus_win_free_error_string (emsg);
323 else if (sitter->have_child_status)
326 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
327 "Process %s exited with status %d",
328 sitter->executable, sitter->child_status);
333 dbus_set_error (error, DBUS_ERROR_FAILED,
334 "Process %s exited, status unknown",
341 _dbus_babysitter_set_watch_functions (DBusBabysitter *sitter,
342 DBusAddWatchFunction add_function,
343 DBusRemoveWatchFunction remove_function,
344 DBusWatchToggledFunction toggled_function,
346 DBusFreeFunction free_data_function)
349 return _dbus_watch_list_set_functions (sitter->watches,
358 handle_watch (DBusWatch *watch,
359 unsigned int condition,
362 DBusBabysitter *sitter = data;
364 /* On Unix dbus-spawn uses a babysitter *process*, thus it has to
365 * actually send the exit statuses, error codes and whatnot through
366 * sockets and/or pipes. On Win32, the babysitter is jus a thread,
367 * so it can set the status fields directly in the babysitter struct
368 * just fine. The socket pipe is used just so we can watch it with
369 * select(), as soon as anything is written to it we know that the
370 * babysitter thread has recorded the status in the babysitter
375 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
377 sitter->socket_to_babysitter = -1;
382 /* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
384 protect_argv (char **argv,
392 *new_argv = dbus_malloc ((argc + 1) * sizeof (char *));
393 if (*new_argv == NULL)
396 for (i = 0; i < argc; i++)
397 (*new_argv)[i] = NULL;
399 /* Quote each argv element if necessary, so that it will get
400 * reconstructed correctly in the C runtime startup code. Note that
401 * the unquoting algorithm in the C runtime is really weird, and
402 * rather different than what Unix shells do. See stdargv.c in the C
403 * runtime sources (in the Platform SDK, in src/crt).
405 * Note that an new_argv[0] constructed by this function should
406 * *not* be passed as the filename argument to a spawn* or exec*
407 * family function. That argument should be the real file name
408 * without any quoting.
410 for (i = 0; i < argc; i++)
415 int need_dblquotes = FALSE;
418 if (*p == ' ' || *p == '\t')
419 need_dblquotes = TRUE;
425 while (*pp && *pp == '\\')
434 q = (*new_argv)[i] = dbus_malloc (len + need_dblquotes*2 + 1);
452 while (*pp && *pp == '\\')
464 /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (*new_argv)[i]); */
466 (*new_argv)[argc] = NULL;
472 /* From GPGME, relicensed by g10 Code GmbH. */
474 build_commandline (char **argv)
482 for (i = 0; argv[i]; i++)
483 n += strlen (argv[i]) + 1;
486 buf = p = malloc (n);
489 for (i = 0; argv[i]; i++)
492 p += strlen (argv[i]);
504 spawn_program (const char* name, char** argv, char** envp)
506 PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
512 arg_string = build_commandline (argv + 1);
514 arg_string = build_commandline (argv);
517 return INVALID_HANDLE_VALUE;
519 memset (&si, 0, sizeof (si));
521 result = CreateProcessA (name, arg_string, NULL, NULL, FALSE, 0,
522 envp, NULL, &si, &pi);
525 return INVALID_HANDLE_VALUE;
527 CloseHandle (pi.hThread);
532 static DWORD __stdcall
533 babysitter (void *parameter)
535 DBusBabysitter *sitter = (DBusBabysitter *) parameter;
538 _dbus_babysitter_ref (sitter);
540 if (sitter->child_setup)
543 (*sitter->child_setup) (sitter->user_data);
546 _dbus_verbose ("babysitter: spawning %s\n", sitter->executable);
549 sitter->child_handle = spawn_program (sitter->executable,
550 sitter->argv, sitter->envp);
553 if (sitter->child_handle == (HANDLE) -1)
555 sitter->child_handle = NULL;
556 sitter->have_spawn_errno = TRUE;
557 sitter->spawn_errno = GetLastError();
561 SetEvent (sitter->start_sync_event);
563 if (sitter->child_handle != NULL)
569 WaitForSingleObject (sitter->child_handle, INFINITE);
572 ret = GetExitCodeProcess (sitter->child_handle, &status);
574 sitter->child_status = status;
575 sitter->have_child_status = TRUE;
577 CloseHandle (sitter->child_handle);
578 sitter->child_handle = NULL;
581 #ifdef DBUS_BUILD_TESTS
582 SetEvent (sitter->end_sync_event);
586 send (sitter->socket_to_main, " ", 1, 0);
588 _dbus_babysitter_unref (sitter);
594 _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
597 DBusSpawnChildSetupFunc child_setup,
601 DBusBabysitter *sitter;
602 HANDLE sitter_thread;
603 DWORD sitter_thread_id;
605 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
610 sitter = _dbus_babysitter_new ();
613 _DBUS_SET_OOM (error);
617 sitter->child_setup = child_setup;
618 sitter->user_data = user_data;
620 sitter->executable = _dbus_strdup (argv[0]);
621 if (sitter->executable == NULL)
623 _DBUS_SET_OOM (error);
628 if (!_dbus_full_duplex_pipe (&sitter->socket_to_babysitter,
629 &sitter->socket_to_main,
633 sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter,
635 TRUE, handle_watch, sitter, NULL);
637 if (sitter->sitter_watch == NULL)
639 _DBUS_SET_OOM (error);
644 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
646 _DBUS_SET_OOM (error);
650 sitter->argc = protect_argv (argv, &sitter->argv);
651 if (sitter->argc == -1)
653 _DBUS_SET_OOM (error);
659 sitter_thread = (HANDLE) CreateThread (NULL, 0, babysitter,
660 sitter, 0, &sitter_thread_id);
662 if (sitter_thread == 0)
665 dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
666 "Failed to create new thread");
669 CloseHandle (sitter_thread);
672 WaitForSingleObject (sitter->start_sync_event, INFINITE);
675 if (sitter_p != NULL)
678 _dbus_babysitter_unref (sitter);
680 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
686 _dbus_babysitter_unref (sitter);
691 #ifdef DBUS_BUILD_TESTS
693 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
696 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
698 if (sitter->child_handle == NULL)
701 WaitForSingleObject (sitter->end_sync_event, INFINITE);
705 check_spawn_nonexistent (void *data)
707 char *argv[4] = { NULL, NULL, NULL, NULL };
708 DBusBabysitter *sitter;
713 dbus_error_init (&error);
715 /*** Test launching nonexistent binary */
717 argv[0] = "/this/does/not/exist/32542sdgafgafdg";
718 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
722 _dbus_babysitter_block_for_child_exit (sitter);
723 _dbus_babysitter_set_child_exit_error (sitter, &error);
727 _dbus_babysitter_unref (sitter);
729 if (!dbus_error_is_set (&error))
731 _dbus_warn ("Did not get an error launching nonexistent executable\n");
735 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
736 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
738 _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
739 error.name, error.message);
740 dbus_error_free (&error);
744 dbus_error_free (&error);
750 check_spawn_segfault (void *data)
752 char *argv[4] = { NULL, NULL, NULL, NULL };
753 DBusBabysitter *sitter;
758 dbus_error_init (&error);
760 /*** Test launching segfault binary */
762 argv[0] = TEST_SEGFAULT_BINARY;
763 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
767 _dbus_babysitter_block_for_child_exit (sitter);
768 _dbus_babysitter_set_child_exit_error (sitter, &error);
772 _dbus_babysitter_unref (sitter);
774 if (!dbus_error_is_set (&error))
776 _dbus_warn ("Did not get an error launching segfaulting binary\n");
780 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
781 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
783 _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
784 error.name, error.message);
785 dbus_error_free (&error);
789 dbus_error_free (&error);
795 check_spawn_exit (void *data)
797 char *argv[4] = { NULL, NULL, NULL, NULL };
798 DBusBabysitter *sitter;
803 dbus_error_init (&error);
805 /*** Test launching exit failure binary */
807 argv[0] = TEST_EXIT_BINARY;
808 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
812 _dbus_babysitter_block_for_child_exit (sitter);
813 _dbus_babysitter_set_child_exit_error (sitter, &error);
817 _dbus_babysitter_unref (sitter);
819 if (!dbus_error_is_set (&error))
821 _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
825 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
826 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
828 _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
829 error.name, error.message);
830 dbus_error_free (&error);
834 dbus_error_free (&error);
840 check_spawn_and_kill (void *data)
842 char *argv[4] = { NULL, NULL, NULL, NULL };
843 DBusBabysitter *sitter;
848 dbus_error_init (&error);
850 /*** Test launching sleeping binary then killing it */
852 argv[0] = TEST_SLEEP_FOREVER_BINARY;
853 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
857 _dbus_babysitter_kill_child (sitter);
859 _dbus_babysitter_block_for_child_exit (sitter);
861 _dbus_babysitter_set_child_exit_error (sitter, &error);
865 _dbus_babysitter_unref (sitter);
867 if (!dbus_error_is_set (&error))
869 _dbus_warn ("Did not get an error after killing spawned binary\n");
873 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
874 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
876 _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
877 error.name, error.message);
878 dbus_error_free (&error);
882 dbus_error_free (&error);
888 _dbus_spawn_test (const char *test_data_dir)
890 if (!_dbus_test_oom_handling ("spawn_nonexistent",
891 check_spawn_nonexistent,
895 /* Don't run the obnoxious segfault test by default,
896 * it's a pain to have to click all those error boxes.
898 if (getenv ("DO_SEGFAULT_TEST"))
899 if (!_dbus_test_oom_handling ("spawn_segfault",
900 check_spawn_segfault,
904 if (!_dbus_test_oom_handling ("spawn_exit",
909 if (!_dbus_test_oom_handling ("spawn_and_kill",
910 check_spawn_and_kill,