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;
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;
85 DBusBabysitterFinishedFunc finished_cb;
88 dbus_bool_t have_spawn_errno;
90 dbus_bool_t have_child_status;
94 static DBusBabysitter*
95 _dbus_babysitter_new (void)
97 DBusBabysitter *sitter;
99 sitter = dbus_new0 (DBusBabysitter, 1);
103 sitter->refcount = 1;
105 sitter->start_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
106 if (sitter->start_sync_event == NULL)
108 _dbus_babysitter_unref (sitter);
112 #ifdef DBUS_BUILD_TESTS
113 sitter->end_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
114 if (sitter->end_sync_event == NULL)
116 _dbus_babysitter_unref (sitter);
121 sitter->child_handle = NULL;
123 sitter->socket_to_babysitter = sitter->socket_to_main = -1;
129 sitter->watches = _dbus_watch_list_new ();
130 if (sitter->watches == NULL)
132 _dbus_babysitter_unref (sitter);
136 sitter->have_spawn_errno = FALSE;
137 sitter->have_child_status = FALSE;
143 * Increment the reference count on the babysitter object.
145 * @param sitter the babysitter
146 * @returns the babysitter
149 _dbus_babysitter_ref (DBusBabysitter *sitter)
152 _dbus_assert (sitter != NULL);
153 _dbus_assert (sitter->refcount > 0);
155 sitter->refcount += 1;
161 close_socket_to_babysitter (DBusBabysitter *sitter)
163 _dbus_verbose ("Closing babysitter\n");
165 if (sitter->sitter_watch != NULL)
167 _dbus_assert (sitter->watches != NULL);
168 _dbus_watch_list_remove_watch (sitter->watches, sitter->sitter_watch);
169 _dbus_watch_invalidate (sitter->sitter_watch);
170 _dbus_watch_unref (sitter->sitter_watch);
171 sitter->sitter_watch = NULL;
174 if (sitter->socket_to_babysitter != -1)
176 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
177 sitter->socket_to_babysitter = -1;
182 * Decrement the reference count on the babysitter object.
184 * @param sitter the babysitter
187 _dbus_babysitter_unref (DBusBabysitter *sitter)
192 _dbus_assert (sitter != NULL);
193 _dbus_assert (sitter->refcount > 0);
195 sitter->refcount -= 1;
197 if (sitter->refcount == 0)
199 close_socket_to_babysitter (sitter);
201 if (sitter->socket_to_main != -1)
203 _dbus_close_socket (sitter->socket_to_main, NULL);
204 sitter->socket_to_main = -1;
208 if (sitter->argv != NULL)
210 for (i = 0; i < sitter->argc; i++)
211 if (sitter->argv[i] != NULL)
213 dbus_free (sitter->argv[i]);
214 sitter->argv[i] = NULL;
216 dbus_free (sitter->argv);
220 if (sitter->envp != NULL)
222 char **e = sitter->envp;
226 dbus_free (sitter->envp);
230 if (sitter->child_handle != NULL)
232 CloseHandle (sitter->child_handle);
233 sitter->child_handle = NULL;
236 if (sitter->sitter_watch)
238 _dbus_watch_invalidate (sitter->sitter_watch);
239 _dbus_watch_unref (sitter->sitter_watch);
240 sitter->sitter_watch = NULL;
244 _dbus_watch_list_free (sitter->watches);
246 if (sitter->start_sync_event != NULL)
249 CloseHandle (sitter->start_sync_event);
250 sitter->start_sync_event = NULL;
253 #ifdef DBUS_BUILD_TESTS
254 if (sitter->end_sync_event != NULL)
256 CloseHandle (sitter->end_sync_event);
257 sitter->end_sync_event = NULL;
261 dbus_free (sitter->executable);
268 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
271 if (sitter->child_handle == NULL)
272 return; /* child is already dead, or we're so hosed we'll never recover */
275 TerminateProcess (sitter->child_handle, 12345);
279 * Checks whether the child has exited, without blocking.
281 * @param sitter the babysitter
284 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
287 return (sitter->child_handle == NULL);
291 * Gets the exit status of the child. We do this so implementation specific
292 * detail is not cluttering up dbus, for example the system launcher code.
293 * This can only be called if the child has exited, i.e. call
294 * _dbus_babysitter_get_child_exited(). It returns FALSE if the child
295 * did not return a status code, e.g. because the child was signaled
296 * or we failed to ever launch the child in the first place.
298 * @param sitter the babysitter
299 * @param status the returned status code
300 * @returns #FALSE on failure
303 _dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
306 if (!_dbus_babysitter_get_child_exited (sitter))
307 _dbus_assert_not_reached ("Child has not exited");
309 if (!sitter->have_child_status ||
310 sitter->child_status == STILL_ACTIVE)
313 *status = sitter->child_status;
318 * Sets the #DBusError with an explanation of why the spawned
319 * child process exited (on a signal, or whatever). If
320 * the child process has not exited, does nothing (error
321 * will remain unset).
323 * @param sitter the babysitter
324 * @param error an error to fill in
327 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
331 if (!_dbus_babysitter_get_child_exited (sitter))
335 if (sitter->have_spawn_errno)
337 char *emsg = _dbus_win_error_string (sitter->spawn_errno);
338 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
339 "Failed to execute program %s: %s",
340 sitter->executable, emsg);
341 _dbus_win_free_error_string (emsg);
343 else if (sitter->have_child_status)
346 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
347 "Process %s exited with status %d",
348 sitter->executable, sitter->child_status);
353 dbus_set_error (error, DBUS_ERROR_FAILED,
354 "Process %s exited, status unknown",
361 _dbus_babysitter_set_watch_functions (DBusBabysitter *sitter,
362 DBusAddWatchFunction add_function,
363 DBusRemoveWatchFunction remove_function,
364 DBusWatchToggledFunction toggled_function,
366 DBusFreeFunction free_data_function)
369 return _dbus_watch_list_set_functions (sitter->watches,
378 handle_watch (DBusWatch *watch,
379 unsigned int condition,
382 DBusBabysitter *sitter = data;
384 /* On Unix dbus-spawn uses a babysitter *process*, thus it has to
385 * actually send the exit statuses, error codes and whatnot through
386 * sockets and/or pipes. On Win32, the babysitter is jus a thread,
387 * so it can set the status fields directly in the babysitter struct
388 * just fine. The socket pipe is used just so we can watch it with
389 * select(), as soon as anything is written to it we know that the
390 * babysitter thread has recorded the status in the babysitter
395 close_socket_to_babysitter (sitter);
398 if (_dbus_babysitter_get_child_exited (sitter) &&
399 sitter->finished_cb != NULL)
401 sitter->finished_cb (sitter, sitter->finished_data);
402 sitter->finished_cb = NULL;
408 /* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
410 protect_argv (char **argv,
418 *new_argv = dbus_malloc ((argc + 1) * sizeof (char *));
419 if (*new_argv == NULL)
422 for (i = 0; i < argc; i++)
423 (*new_argv)[i] = NULL;
425 /* Quote each argv element if necessary, so that it will get
426 * reconstructed correctly in the C runtime startup code. Note that
427 * the unquoting algorithm in the C runtime is really weird, and
428 * rather different than what Unix shells do. See stdargv.c in the C
429 * runtime sources (in the Platform SDK, in src/crt).
431 * Note that an new_argv[0] constructed by this function should
432 * *not* be passed as the filename argument to a spawn* or exec*
433 * family function. That argument should be the real file name
434 * without any quoting.
436 for (i = 0; i < argc; i++)
441 int need_dblquotes = FALSE;
444 if (*p == ' ' || *p == '\t')
445 need_dblquotes = TRUE;
451 while (*pp && *pp == '\\')
460 q = (*new_argv)[i] = dbus_malloc (len + need_dblquotes*2 + 1);
478 while (*pp && *pp == '\\')
490 /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (*new_argv)[i]); */
492 (*new_argv)[argc] = NULL;
498 /* From GPGME, relicensed by g10 Code GmbH. */
500 compose_string (char **strings, char separator)
507 if (!strings || !strings[0])
509 for (i = 0; strings[i]; i++)
510 n += strlen (strings[i]) + 1;
513 buf = p = malloc (n);
516 for (i = 0; strings[i]; i++)
518 strcpy (p, strings[i]);
519 p += strlen (strings[i]);
530 build_commandline (char **argv)
532 return compose_string (argv, ' ');
536 build_env_string (char** envp)
538 return compose_string (envp, '\0');
542 spawn_program (char* name, char** argv, char** envp)
544 PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
546 char *arg_string, *env_string;
548 char exe_path[MAX_PATH];
552 arg_string = build_commandline (argv + 1);
556 arg_string = build_commandline (argv);
559 return INVALID_HANDLE_VALUE;
561 env_string = build_env_string(envp);
564 // handle relative pathes
565 if (strlen(name) > 2 && name[0] != '\\' && name[0] != '/' && name[1] != ':')
567 char install_root[2*MAX_PATH];
570 _dbus_verbose ("babysitter: spawning %s", name);
571 if (!_dbus_get_install_root (install_root, sizeof(install_root)))
572 return INVALID_HANDLE_VALUE;
574 strcat(install_root,name);
576 // add exe extension, if not present
577 p = strrchr(name,'.');
579 strcat(install_root,".exe");
581 // convert '/' into '\\'
582 while((p = strchr(install_root,'/')) != 0)
585 // separate path from filename
586 p = strrchr(install_root,'\\');
587 // no complete path: error condition
589 return INVALID_HANDLE_VALUE;
591 if (!SearchPathA(install_root, p+1, NULL, sizeof(exe_path), exe_path, &lpFile))
592 return INVALID_HANDLE_VALUE;
596 strncpy(exe_path,name,MAX_PATH);
598 memset (&si, 0, sizeof (si));
600 result = CreateProcessA (exe_path, arg_string, NULL, NULL, FALSE, 0,
601 (LPVOID)env_string, NULL, &si, &pi);
607 return INVALID_HANDLE_VALUE;
609 CloseHandle (pi.hThread);
614 static DWORD __stdcall
615 babysitter (void *parameter)
617 DBusBabysitter *sitter = (DBusBabysitter *) parameter;
620 _dbus_babysitter_ref (sitter);
622 if (sitter->child_setup)
625 (*sitter->child_setup) (sitter->user_data);
628 _dbus_verbose ("babysitter: spawning %s\n", sitter->executable);
631 sitter->child_handle = spawn_program (sitter->executable,
632 sitter->argv, sitter->envp);
635 if (sitter->child_handle == (HANDLE) -1)
637 sitter->child_handle = NULL;
638 sitter->have_spawn_errno = TRUE;
639 sitter->spawn_errno = GetLastError();
643 SetEvent (sitter->start_sync_event);
645 if (sitter->child_handle != NULL)
651 WaitForSingleObject (sitter->child_handle, INFINITE);
654 ret = GetExitCodeProcess (sitter->child_handle, &status);
656 sitter->child_status = status;
657 sitter->have_child_status = TRUE;
659 CloseHandle (sitter->child_handle);
660 sitter->child_handle = NULL;
663 #ifdef DBUS_BUILD_TESTS
664 SetEvent (sitter->end_sync_event);
668 send (sitter->socket_to_main, " ", 1, 0);
670 _dbus_babysitter_unref (sitter);
676 _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
679 DBusSpawnChildSetupFunc child_setup,
683 DBusBabysitter *sitter;
684 HANDLE sitter_thread;
685 DWORD sitter_thread_id;
687 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
692 sitter = _dbus_babysitter_new ();
695 _DBUS_SET_OOM (error);
699 sitter->child_setup = child_setup;
700 sitter->user_data = user_data;
702 sitter->executable = _dbus_strdup (argv[0]);
703 if (sitter->executable == NULL)
705 _DBUS_SET_OOM (error);
710 if (!_dbus_full_duplex_pipe (&sitter->socket_to_babysitter,
711 &sitter->socket_to_main,
715 sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter,
717 TRUE, handle_watch, sitter, NULL);
719 if (sitter->sitter_watch == NULL)
721 _DBUS_SET_OOM (error);
726 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
728 /* we need to free it early so the destructor won't try to remove it
729 * without it having been added, which DBusLoop doesn't allow */
730 _dbus_watch_invalidate (sitter->sitter_watch);
731 _dbus_watch_unref (sitter->sitter_watch);
732 sitter->sitter_watch = NULL;
734 _DBUS_SET_OOM (error);
738 sitter->argc = protect_argv (argv, &sitter->argv);
739 if (sitter->argc == -1)
741 _DBUS_SET_OOM (error);
747 sitter_thread = (HANDLE) CreateThread (NULL, 0, babysitter,
748 sitter, 0, &sitter_thread_id);
750 if (sitter_thread == 0)
753 dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
754 "Failed to create new thread");
757 CloseHandle (sitter_thread);
760 WaitForSingleObject (sitter->start_sync_event, INFINITE);
763 if (sitter_p != NULL)
766 _dbus_babysitter_unref (sitter);
768 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
774 _dbus_babysitter_unref (sitter);
780 _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
781 DBusBabysitterFinishedFunc finished,
784 sitter->finished_cb = finished;
785 sitter->finished_data = user_data;
788 #ifdef DBUS_BUILD_TESTS
791 get_test_exec (const char *exe,
792 DBusString *scratch_space)
794 const char *dbus_test_exec;
796 dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
798 if (dbus_test_exec == NULL)
799 dbus_test_exec = DBUS_TEST_EXEC;
801 if (!_dbus_string_init (scratch_space))
804 if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
805 dbus_test_exec, exe, DBUS_EXEEXT))
807 _dbus_string_free (scratch_space);
811 return _dbus_string_get_data (scratch_space);
814 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
817 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
819 if (sitter->child_handle == NULL)
822 WaitForSingleObject (sitter->end_sync_event, INFINITE);
826 check_spawn_nonexistent (void *data)
828 char *argv[4] = { NULL, NULL, NULL, NULL };
829 DBusBabysitter *sitter;
834 dbus_error_init (&error);
836 /*** Test launching nonexistent binary */
838 argv[0] = "/this/does/not/exist/32542sdgafgafdg";
839 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
843 _dbus_babysitter_block_for_child_exit (sitter);
844 _dbus_babysitter_set_child_exit_error (sitter, &error);
848 _dbus_babysitter_unref (sitter);
850 if (!dbus_error_is_set (&error))
852 _dbus_warn ("Did not get an error launching nonexistent executable\n");
856 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
857 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
859 _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
860 error.name, error.message);
861 dbus_error_free (&error);
865 dbus_error_free (&error);
871 check_spawn_segfault (void *data)
873 char *argv[4] = { NULL, NULL, NULL, NULL };
874 DBusBabysitter *sitter;
880 dbus_error_init (&error);
882 /*** Test launching segfault binary */
884 argv[0] = get_test_exec ("test-segfault", &argv0);
888 /* OOM was simulated, never mind */
892 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
896 _dbus_babysitter_block_for_child_exit (sitter);
897 _dbus_babysitter_set_child_exit_error (sitter, &error);
900 _dbus_string_free (&argv0);
903 _dbus_babysitter_unref (sitter);
905 if (!dbus_error_is_set (&error))
907 _dbus_warn ("Did not get an error launching segfaulting binary\n");
911 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
912 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
914 _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
915 error.name, error.message);
916 dbus_error_free (&error);
920 dbus_error_free (&error);
926 check_spawn_exit (void *data)
928 char *argv[4] = { NULL, NULL, NULL, NULL };
929 DBusBabysitter *sitter;
935 dbus_error_init (&error);
937 /*** Test launching exit failure binary */
939 argv[0] = get_test_exec ("test-exit", &argv0);
943 /* OOM was simulated, never mind */
947 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
951 _dbus_babysitter_block_for_child_exit (sitter);
952 _dbus_babysitter_set_child_exit_error (sitter, &error);
955 _dbus_string_free (&argv0);
958 _dbus_babysitter_unref (sitter);
960 if (!dbus_error_is_set (&error))
962 _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
966 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
967 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
969 _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
970 error.name, error.message);
971 dbus_error_free (&error);
975 dbus_error_free (&error);
981 check_spawn_and_kill (void *data)
983 char *argv[4] = { NULL, NULL, NULL, NULL };
984 DBusBabysitter *sitter;
990 dbus_error_init (&error);
992 /*** Test launching sleeping binary then killing it */
994 argv[0] = get_test_exec ("test-sleep-forever", &argv0);
998 /* OOM was simulated, never mind */
1002 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
1006 _dbus_babysitter_kill_child (sitter);
1008 _dbus_babysitter_block_for_child_exit (sitter);
1010 _dbus_babysitter_set_child_exit_error (sitter, &error);
1013 _dbus_string_free (&argv0);
1016 _dbus_babysitter_unref (sitter);
1018 if (!dbus_error_is_set (&error))
1020 _dbus_warn ("Did not get an error after killing spawned binary\n");
1024 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
1025 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
1027 _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
1028 error.name, error.message);
1029 dbus_error_free (&error);
1033 dbus_error_free (&error);
1039 _dbus_spawn_test (const char *test_data_dir)
1041 if (!_dbus_test_oom_handling ("spawn_nonexistent",
1042 check_spawn_nonexistent,
1046 /* Don't run the obnoxious segfault test by default,
1047 * it's a pain to have to click all those error boxes.
1049 if (getenv ("DO_SEGFAULT_TEST"))
1050 if (!_dbus_test_oom_handling ("spawn_segfault",
1051 check_spawn_segfault,
1055 if (!_dbus_test_oom_handling ("spawn_exit",
1060 if (!_dbus_test_oom_handling ("spawn_and_kill",
1061 check_spawn_and_kill,