5 #if !defined(SPAWN_DEBUG) || defined(_MSC_VER)
8 #define PING() fprintf (stderr, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__); fflush (stderr)
16 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
17 /* dbus-spawn-win32.c Wrapper around g_spawn
19 * Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
20 * Copyright (C) 2003 CodeFactory AB
21 * Copyright (C) 2005 Novell, Inc.
23 * Licensed under the Academic Free License version 2.1
25 * This program is free software; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
40 #include "dbus-spawn.h"
41 #include "dbus-sysdeps.h"
42 #include "dbus-sysdeps-win.h"
43 #include "dbus-internals.h"
44 #include "dbus-test.h"
45 #include "dbus-protocol.h"
47 #define WIN32_LEAN_AND_MEAN
49 //#include <windows.h>
59 * Babysitter implementation details
65 HANDLE start_sync_event;
66 #ifdef DBUS_BUILD_TESTS
68 HANDLE end_sync_event;
72 DBusSpawnChildSetupFunc child_setup;
80 int socket_to_babysitter; /* Connection to the babysitter thread */
83 DBusWatchList *watches;
84 DBusWatch *sitter_watch;
86 dbus_bool_t have_spawn_errno;
88 dbus_bool_t have_child_status;
92 static DBusBabysitter*
93 _dbus_babysitter_new (void)
95 DBusBabysitter *sitter;
97 sitter = dbus_new0 (DBusBabysitter, 1);
101 sitter->refcount = 1;
103 sitter->start_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
104 if (sitter->start_sync_event == NULL)
106 _dbus_babysitter_unref (sitter);
110 #ifdef DBUS_BUILD_TESTS
111 sitter->end_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
112 if (sitter->end_sync_event == NULL)
114 _dbus_babysitter_unref (sitter);
119 sitter->child_handle = NULL;
121 sitter->socket_to_babysitter = sitter->socket_to_main = -1;
127 sitter->watches = _dbus_watch_list_new ();
128 if (sitter->watches == NULL)
130 _dbus_babysitter_unref (sitter);
134 sitter->have_spawn_errno = FALSE;
135 sitter->have_child_status = FALSE;
141 * Increment the reference count on the babysitter object.
143 * @param sitter the babysitter
144 * @returns the babysitter
147 _dbus_babysitter_ref (DBusBabysitter *sitter)
150 _dbus_assert (sitter != NULL);
151 _dbus_assert (sitter->refcount > 0);
153 sitter->refcount += 1;
159 * Decrement the reference count on the babysitter object.
161 * @param sitter the babysitter
164 _dbus_babysitter_unref (DBusBabysitter *sitter)
169 _dbus_assert (sitter != NULL);
170 _dbus_assert (sitter->refcount > 0);
172 sitter->refcount -= 1;
174 if (sitter->refcount == 0)
176 if (sitter->socket_to_babysitter != -1)
178 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
179 sitter->socket_to_babysitter = -1;
182 if (sitter->socket_to_main != -1)
184 _dbus_close_socket (sitter->socket_to_main, NULL);
185 sitter->socket_to_main = -1;
189 if (sitter->argv != NULL)
191 for (i = 0; i < sitter->argc; i++)
192 if (sitter->argv[i] != NULL)
194 dbus_free (sitter->argv[i]);
195 sitter->argv[i] = NULL;
197 dbus_free (sitter->argv);
201 if (sitter->envp != NULL)
203 char **e = sitter->envp;
207 dbus_free (sitter->envp);
211 if (sitter->child_handle != NULL)
213 CloseHandle (sitter->child_handle);
214 sitter->child_handle = NULL;
217 if (sitter->sitter_watch)
219 _dbus_watch_invalidate (sitter->sitter_watch);
220 _dbus_watch_unref (sitter->sitter_watch);
221 sitter->sitter_watch = NULL;
225 _dbus_watch_list_free (sitter->watches);
227 if (sitter->start_sync_event != NULL)
230 CloseHandle (sitter->start_sync_event);
231 sitter->start_sync_event = NULL;
234 #ifdef DBUS_BUILD_TESTS
235 if (sitter->end_sync_event != NULL)
237 CloseHandle (sitter->end_sync_event);
238 sitter->end_sync_event = NULL;
242 dbus_free (sitter->executable);
249 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
252 if (sitter->child_handle == NULL)
253 return; /* child is already dead, or we're so hosed we'll never recover */
256 TerminateProcess (sitter->child_handle, 12345);
260 * Checks whether the child has exited, without blocking.
262 * @param sitter the babysitter
265 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
268 return (sitter->child_handle == NULL);
272 * Gets the exit status of the child. We do this so implementation specific
273 * detail is not cluttering up dbus, for example the system launcher code.
274 * This can only be called if the child has exited, i.e. call
275 * _dbus_babysitter_get_child_exited(). It returns FALSE if the child
276 * did not return a status code, e.g. because the child was signaled
277 * or we failed to ever launch the child in the first place.
279 * @param sitter the babysitter
280 * @param status the returned status code
281 * @returns #FALSE on failure
284 _dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
287 if (!_dbus_babysitter_get_child_exited (sitter))
288 _dbus_assert_not_reached ("Child has not exited");
290 if (!sitter->have_child_status ||
291 sitter->child_status == STILL_ACTIVE)
294 *status = sitter->child_status;
299 * Sets the #DBusError with an explanation of why the spawned
300 * child process exited (on a signal, or whatever). If
301 * the child process has not exited, does nothing (error
302 * will remain unset).
304 * @param sitter the babysitter
305 * @param error an error to fill in
308 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
312 if (!_dbus_babysitter_get_child_exited (sitter))
316 if (sitter->have_spawn_errno)
318 char *emsg = _dbus_win_error_string (sitter->spawn_errno);
319 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
320 "Failed to execute program %s: %s",
321 sitter->executable, emsg);
322 _dbus_win_free_error_string (emsg);
324 else if (sitter->have_child_status)
327 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
328 "Process %s exited with status %d",
329 sitter->executable, sitter->child_status);
334 dbus_set_error (error, DBUS_ERROR_FAILED,
335 "Process %s exited, status unknown",
342 _dbus_babysitter_set_watch_functions (DBusBabysitter *sitter,
343 DBusAddWatchFunction add_function,
344 DBusRemoveWatchFunction remove_function,
345 DBusWatchToggledFunction toggled_function,
347 DBusFreeFunction free_data_function)
350 return _dbus_watch_list_set_functions (sitter->watches,
359 handle_watch (DBusWatch *watch,
360 unsigned int condition,
363 DBusBabysitter *sitter = data;
365 /* On Unix dbus-spawn uses a babysitter *process*, thus it has to
366 * actually send the exit statuses, error codes and whatnot through
367 * sockets and/or pipes. On Win32, the babysitter is jus a thread,
368 * so it can set the status fields directly in the babysitter struct
369 * just fine. The socket pipe is used just so we can watch it with
370 * select(), as soon as anything is written to it we know that the
371 * babysitter thread has recorded the status in the babysitter
376 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
378 sitter->socket_to_babysitter = -1;
383 /* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
385 protect_argv (char **argv,
393 *new_argv = dbus_malloc ((argc + 1) * sizeof (char *));
394 if (*new_argv == NULL)
397 for (i = 0; i < argc; i++)
398 (*new_argv)[i] = NULL;
400 /* Quote each argv element if necessary, so that it will get
401 * reconstructed correctly in the C runtime startup code. Note that
402 * the unquoting algorithm in the C runtime is really weird, and
403 * rather different than what Unix shells do. See stdargv.c in the C
404 * runtime sources (in the Platform SDK, in src/crt).
406 * Note that an new_argv[0] constructed by this function should
407 * *not* be passed as the filename argument to a spawn* or exec*
408 * family function. That argument should be the real file name
409 * without any quoting.
411 for (i = 0; i < argc; i++)
416 int need_dblquotes = FALSE;
419 if (*p == ' ' || *p == '\t')
420 need_dblquotes = TRUE;
426 while (*pp && *pp == '\\')
435 q = (*new_argv)[i] = dbus_malloc (len + need_dblquotes*2 + 1);
453 while (*pp && *pp == '\\')
465 /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (*new_argv)[i]); */
467 (*new_argv)[argc] = NULL;
473 /* From GPGME, relicensed by g10 Code GmbH. */
475 build_commandline (char **argv)
483 for (i = 0; argv[i]; i++)
484 n += strlen (argv[i]) + 1;
487 buf = p = malloc (n);
490 for (i = 0; argv[i]; i++)
493 p += strlen (argv[i]);
505 spawn_program (const char* name, char** argv, char** envp)
507 PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
513 arg_string = build_commandline (argv + 1);
515 arg_string = build_commandline (argv);
518 return INVALID_HANDLE_VALUE;
520 memset (&si, 0, sizeof (si));
522 result = CreateProcessA (name, arg_string, NULL, NULL, FALSE, 0,
523 envp, NULL, &si, &pi);
526 return INVALID_HANDLE_VALUE;
528 CloseHandle (pi.hThread);
533 static DWORD __stdcall
534 babysitter (void *parameter)
536 DBusBabysitter *sitter = (DBusBabysitter *) parameter;
539 _dbus_babysitter_ref (sitter);
541 if (sitter->child_setup)
544 (*sitter->child_setup) (sitter->user_data);
547 _dbus_verbose ("babysitter: spawning %s\n", sitter->executable);
550 sitter->child_handle = spawn_program (sitter->executable,
551 sitter->argv, sitter->envp);
554 if (sitter->child_handle == (HANDLE) -1)
556 sitter->child_handle = NULL;
557 sitter->have_spawn_errno = TRUE;
558 sitter->spawn_errno = GetLastError();
562 SetEvent (sitter->start_sync_event);
564 if (sitter->child_handle != NULL)
570 WaitForSingleObject (sitter->child_handle, INFINITE);
573 ret = GetExitCodeProcess (sitter->child_handle, &status);
575 sitter->child_status = status;
576 sitter->have_child_status = TRUE;
578 CloseHandle (sitter->child_handle);
579 sitter->child_handle = NULL;
582 #ifdef DBUS_BUILD_TESTS
583 SetEvent (sitter->end_sync_event);
587 send (sitter->socket_to_main, " ", 1, 0);
589 _dbus_babysitter_unref (sitter);
595 _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
598 DBusSpawnChildSetupFunc child_setup,
602 DBusBabysitter *sitter;
603 HANDLE sitter_thread;
604 DWORD sitter_thread_id;
606 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
611 sitter = _dbus_babysitter_new ();
614 _DBUS_SET_OOM (error);
618 sitter->child_setup = child_setup;
619 sitter->user_data = user_data;
621 sitter->executable = _dbus_strdup (argv[0]);
622 if (sitter->executable == NULL)
624 _DBUS_SET_OOM (error);
629 if (!_dbus_full_duplex_pipe (&sitter->socket_to_babysitter,
630 &sitter->socket_to_main,
634 sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter,
636 TRUE, handle_watch, sitter, NULL);
638 if (sitter->sitter_watch == NULL)
640 _DBUS_SET_OOM (error);
645 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
647 _DBUS_SET_OOM (error);
651 sitter->argc = protect_argv (argv, &sitter->argv);
652 if (sitter->argc == -1)
654 _DBUS_SET_OOM (error);
660 sitter_thread = (HANDLE) CreateThread (NULL, 0, babysitter,
661 sitter, 0, &sitter_thread_id);
663 if (sitter_thread == 0)
666 dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
667 "Failed to create new thread");
670 CloseHandle (sitter_thread);
673 WaitForSingleObject (sitter->start_sync_event, INFINITE);
676 if (sitter_p != NULL)
679 _dbus_babysitter_unref (sitter);
681 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
687 _dbus_babysitter_unref (sitter);
692 #ifdef DBUS_BUILD_TESTS
694 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
697 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
699 if (sitter->child_handle == NULL)
702 WaitForSingleObject (sitter->end_sync_event, INFINITE);
706 check_spawn_nonexistent (void *data)
708 char *argv[4] = { NULL, NULL, NULL, NULL };
709 DBusBabysitter *sitter;
714 dbus_error_init (&error);
716 /*** Test launching nonexistent binary */
718 argv[0] = "/this/does/not/exist/32542sdgafgafdg";
719 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
723 _dbus_babysitter_block_for_child_exit (sitter);
724 _dbus_babysitter_set_child_exit_error (sitter, &error);
728 _dbus_babysitter_unref (sitter);
730 if (!dbus_error_is_set (&error))
732 _dbus_warn ("Did not get an error launching nonexistent executable\n");
736 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
737 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
739 _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
740 error.name, error.message);
741 dbus_error_free (&error);
745 dbus_error_free (&error);
751 check_spawn_segfault (void *data)
753 char *argv[4] = { NULL, NULL, NULL, NULL };
754 DBusBabysitter *sitter;
759 dbus_error_init (&error);
761 /*** Test launching segfault binary */
763 argv[0] = TEST_SEGFAULT_BINARY;
764 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
768 _dbus_babysitter_block_for_child_exit (sitter);
769 _dbus_babysitter_set_child_exit_error (sitter, &error);
773 _dbus_babysitter_unref (sitter);
775 if (!dbus_error_is_set (&error))
777 _dbus_warn ("Did not get an error launching segfaulting binary\n");
781 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
782 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
784 _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
785 error.name, error.message);
786 dbus_error_free (&error);
790 dbus_error_free (&error);
796 check_spawn_exit (void *data)
798 char *argv[4] = { NULL, NULL, NULL, NULL };
799 DBusBabysitter *sitter;
804 dbus_error_init (&error);
806 /*** Test launching exit failure binary */
808 argv[0] = TEST_EXIT_BINARY;
809 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
813 _dbus_babysitter_block_for_child_exit (sitter);
814 _dbus_babysitter_set_child_exit_error (sitter, &error);
818 _dbus_babysitter_unref (sitter);
820 if (!dbus_error_is_set (&error))
822 _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
826 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
827 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
829 _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
830 error.name, error.message);
831 dbus_error_free (&error);
835 dbus_error_free (&error);
841 check_spawn_and_kill (void *data)
843 char *argv[4] = { NULL, NULL, NULL, NULL };
844 DBusBabysitter *sitter;
849 dbus_error_init (&error);
851 /*** Test launching sleeping binary then killing it */
853 argv[0] = TEST_SLEEP_FOREVER_BINARY;
854 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
858 _dbus_babysitter_kill_child (sitter);
860 _dbus_babysitter_block_for_child_exit (sitter);
862 _dbus_babysitter_set_child_exit_error (sitter, &error);
866 _dbus_babysitter_unref (sitter);
868 if (!dbus_error_is_set (&error))
870 _dbus_warn ("Did not get an error after killing spawned binary\n");
874 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
875 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
877 _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
878 error.name, error.message);
879 dbus_error_free (&error);
883 dbus_error_free (&error);
889 _dbus_spawn_test (const char *test_data_dir)
891 if (!_dbus_test_oom_handling ("spawn_nonexistent",
892 check_spawn_nonexistent,
896 /* Don't run the obnoxious segfault test by default,
897 * it's a pain to have to click all those error boxes.
899 if (getenv ("DO_SEGFAULT_TEST"))
900 if (!_dbus_test_oom_handling ("spawn_segfault",
901 check_spawn_segfault,
905 if (!_dbus_test_oom_handling ("spawn_exit",
910 if (!_dbus_test_oom_handling ("spawn_and_kill",
911 check_spawn_and_kill,