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;
84 DBusBabysitterFinishedFunc finished_cb;
87 dbus_bool_t have_spawn_errno;
89 dbus_bool_t have_child_status;
93 static DBusBabysitter*
94 _dbus_babysitter_new (void)
96 DBusBabysitter *sitter;
98 sitter = dbus_new0 (DBusBabysitter, 1);
102 sitter->refcount = 1;
104 sitter->start_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
105 if (sitter->start_sync_event == NULL)
107 _dbus_babysitter_unref (sitter);
111 #ifdef DBUS_BUILD_TESTS
112 sitter->end_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
113 if (sitter->end_sync_event == NULL)
115 _dbus_babysitter_unref (sitter);
120 sitter->child_handle = NULL;
122 sitter->socket_to_babysitter = sitter->socket_to_main = -1;
128 sitter->watches = _dbus_watch_list_new ();
129 if (sitter->watches == NULL)
131 _dbus_babysitter_unref (sitter);
135 sitter->have_spawn_errno = FALSE;
136 sitter->have_child_status = FALSE;
142 * Increment the reference count on the babysitter object.
144 * @param sitter the babysitter
145 * @returns the babysitter
148 _dbus_babysitter_ref (DBusBabysitter *sitter)
151 _dbus_assert (sitter != NULL);
152 _dbus_assert (sitter->refcount > 0);
154 sitter->refcount += 1;
160 close_socket_to_babysitter (DBusBabysitter *sitter)
162 _dbus_verbose ("Closing babysitter\n");
164 if (sitter->sitter_watch != NULL)
166 _dbus_assert (sitter->watches != NULL);
167 _dbus_watch_list_remove_watch (sitter->watches, sitter->sitter_watch);
168 _dbus_watch_invalidate (sitter->sitter_watch);
169 _dbus_watch_unref (sitter->sitter_watch);
170 sitter->sitter_watch = NULL;
173 if (sitter->socket_to_babysitter != -1)
175 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
176 sitter->socket_to_babysitter = -1;
181 * Decrement the reference count on the babysitter object.
183 * @param sitter the babysitter
186 _dbus_babysitter_unref (DBusBabysitter *sitter)
191 _dbus_assert (sitter != NULL);
192 _dbus_assert (sitter->refcount > 0);
194 sitter->refcount -= 1;
196 if (sitter->refcount == 0)
198 close_socket_to_babysitter (sitter);
200 if (sitter->socket_to_main != -1)
202 _dbus_close_socket (sitter->socket_to_main, NULL);
203 sitter->socket_to_main = -1;
207 if (sitter->argv != NULL)
209 for (i = 0; i < sitter->argc; i++)
210 if (sitter->argv[i] != NULL)
212 dbus_free (sitter->argv[i]);
213 sitter->argv[i] = NULL;
215 dbus_free (sitter->argv);
219 if (sitter->envp != NULL)
221 char **e = sitter->envp;
225 dbus_free (sitter->envp);
229 if (sitter->child_handle != NULL)
231 CloseHandle (sitter->child_handle);
232 sitter->child_handle = NULL;
235 if (sitter->sitter_watch)
237 _dbus_watch_invalidate (sitter->sitter_watch);
238 _dbus_watch_unref (sitter->sitter_watch);
239 sitter->sitter_watch = NULL;
243 _dbus_watch_list_free (sitter->watches);
245 if (sitter->start_sync_event != NULL)
248 CloseHandle (sitter->start_sync_event);
249 sitter->start_sync_event = NULL;
252 #ifdef DBUS_BUILD_TESTS
253 if (sitter->end_sync_event != NULL)
255 CloseHandle (sitter->end_sync_event);
256 sitter->end_sync_event = NULL;
260 dbus_free (sitter->executable);
267 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
270 if (sitter->child_handle == NULL)
271 return; /* child is already dead, or we're so hosed we'll never recover */
274 TerminateProcess (sitter->child_handle, 12345);
278 * Checks whether the child has exited, without blocking.
280 * @param sitter the babysitter
283 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
286 return (sitter->child_handle == NULL);
290 * Gets the exit status of the child. We do this so implementation specific
291 * detail is not cluttering up dbus, for example the system launcher code.
292 * This can only be called if the child has exited, i.e. call
293 * _dbus_babysitter_get_child_exited(). It returns FALSE if the child
294 * did not return a status code, e.g. because the child was signaled
295 * or we failed to ever launch the child in the first place.
297 * @param sitter the babysitter
298 * @param status the returned status code
299 * @returns #FALSE on failure
302 _dbus_babysitter_get_child_exit_status (DBusBabysitter *sitter,
305 if (!_dbus_babysitter_get_child_exited (sitter))
306 _dbus_assert_not_reached ("Child has not exited");
308 if (!sitter->have_child_status ||
309 sitter->child_status == STILL_ACTIVE)
312 *status = sitter->child_status;
317 * Sets the #DBusError with an explanation of why the spawned
318 * child process exited (on a signal, or whatever). If
319 * the child process has not exited, does nothing (error
320 * will remain unset).
322 * @param sitter the babysitter
323 * @param error an error to fill in
326 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
330 if (!_dbus_babysitter_get_child_exited (sitter))
334 if (sitter->have_spawn_errno)
336 char *emsg = _dbus_win_error_string (sitter->spawn_errno);
337 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
338 "Failed to execute program %s: %s",
339 sitter->executable, emsg);
340 _dbus_win_free_error_string (emsg);
342 else if (sitter->have_child_status)
345 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
346 "Process %s exited with status %d",
347 sitter->executable, sitter->child_status);
352 dbus_set_error (error, DBUS_ERROR_FAILED,
353 "Process %s exited, status unknown",
360 _dbus_babysitter_set_watch_functions (DBusBabysitter *sitter,
361 DBusAddWatchFunction add_function,
362 DBusRemoveWatchFunction remove_function,
363 DBusWatchToggledFunction toggled_function,
365 DBusFreeFunction free_data_function)
368 return _dbus_watch_list_set_functions (sitter->watches,
377 handle_watch (DBusWatch *watch,
378 unsigned int condition,
381 DBusBabysitter *sitter = data;
383 /* On Unix dbus-spawn uses a babysitter *process*, thus it has to
384 * actually send the exit statuses, error codes and whatnot through
385 * sockets and/or pipes. On Win32, the babysitter is jus a thread,
386 * so it can set the status fields directly in the babysitter struct
387 * just fine. The socket pipe is used just so we can watch it with
388 * select(), as soon as anything is written to it we know that the
389 * babysitter thread has recorded the status in the babysitter
394 close_socket_to_babysitter (sitter);
397 if (_dbus_babysitter_get_child_exited (sitter) &&
398 sitter->finished_cb != NULL)
400 sitter->finished_cb (sitter, sitter->finished_data);
401 sitter->finished_cb = NULL;
407 /* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
409 protect_argv (char **argv,
417 *new_argv = dbus_malloc ((argc + 1) * sizeof (char *));
418 if (*new_argv == NULL)
421 for (i = 0; i < argc; i++)
422 (*new_argv)[i] = NULL;
424 /* Quote each argv element if necessary, so that it will get
425 * reconstructed correctly in the C runtime startup code. Note that
426 * the unquoting algorithm in the C runtime is really weird, and
427 * rather different than what Unix shells do. See stdargv.c in the C
428 * runtime sources (in the Platform SDK, in src/crt).
430 * Note that an new_argv[0] constructed by this function should
431 * *not* be passed as the filename argument to a spawn* or exec*
432 * family function. That argument should be the real file name
433 * without any quoting.
435 for (i = 0; i < argc; i++)
440 int need_dblquotes = FALSE;
443 if (*p == ' ' || *p == '\t')
444 need_dblquotes = TRUE;
450 while (*pp && *pp == '\\')
459 q = (*new_argv)[i] = dbus_malloc (len + need_dblquotes*2 + 1);
477 while (*pp && *pp == '\\')
489 /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (*new_argv)[i]); */
491 (*new_argv)[argc] = NULL;
497 /* From GPGME, relicensed by g10 Code GmbH. */
499 compose_string (char **strings, char separator)
506 if (!strings || !strings[0])
508 for (i = 0; strings[i]; i++)
509 n += strlen (strings[i]) + 1;
512 buf = p = malloc (n);
515 for (i = 0; strings[i]; i++)
517 strcpy (p, strings[i]);
518 p += strlen (strings[i]);
529 build_commandline (char **argv)
531 return compose_string (argv, ' ');
535 build_env_string (char** envp)
537 return compose_string (envp, '\0');
541 spawn_program (char* name, char** argv, char** envp)
543 PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
545 char *arg_string, *env_string;
550 arg_string = build_commandline (argv + 1);
554 arg_string = build_commandline (argv);
557 return INVALID_HANDLE_VALUE;
559 env_string = build_env_string(envp);
561 memset (&si, 0, sizeof (si));
564 result = CreateProcessA (name, arg_string, NULL, NULL, FALSE, 0,
566 result = CreateProcessA (NULL, arg_string, NULL, NULL, FALSE, 0,
568 (LPVOID)env_string, NULL, &si, &pi);
574 return INVALID_HANDLE_VALUE;
576 CloseHandle (pi.hThread);
581 static DWORD __stdcall
582 babysitter (void *parameter)
584 DBusBabysitter *sitter = (DBusBabysitter *) parameter;
587 _dbus_babysitter_ref (sitter);
589 if (sitter->child_setup)
592 (*sitter->child_setup) (sitter->user_data);
595 _dbus_verbose ("babysitter: spawning %s\n", sitter->executable);
598 sitter->child_handle = spawn_program (sitter->executable,
599 sitter->argv, sitter->envp);
602 if (sitter->child_handle == (HANDLE) -1)
604 sitter->child_handle = NULL;
605 sitter->have_spawn_errno = TRUE;
606 sitter->spawn_errno = GetLastError();
610 SetEvent (sitter->start_sync_event);
612 if (sitter->child_handle != NULL)
618 WaitForSingleObject (sitter->child_handle, INFINITE);
621 ret = GetExitCodeProcess (sitter->child_handle, &status);
623 sitter->child_status = status;
624 sitter->have_child_status = TRUE;
626 CloseHandle (sitter->child_handle);
627 sitter->child_handle = NULL;
630 #ifdef DBUS_BUILD_TESTS
631 SetEvent (sitter->end_sync_event);
635 send (sitter->socket_to_main, " ", 1, 0);
637 _dbus_babysitter_unref (sitter);
643 _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
646 DBusSpawnChildSetupFunc child_setup,
650 DBusBabysitter *sitter;
651 HANDLE sitter_thread;
652 DWORD sitter_thread_id;
654 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
659 sitter = _dbus_babysitter_new ();
662 _DBUS_SET_OOM (error);
666 sitter->child_setup = child_setup;
667 sitter->user_data = user_data;
669 sitter->executable = _dbus_strdup (argv[0]);
670 if (sitter->executable == NULL)
672 _DBUS_SET_OOM (error);
677 if (!_dbus_full_duplex_pipe (&sitter->socket_to_babysitter,
678 &sitter->socket_to_main,
682 sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter,
684 TRUE, handle_watch, sitter, NULL);
686 if (sitter->sitter_watch == NULL)
688 _DBUS_SET_OOM (error);
693 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
695 /* we need to free it early so the destructor won't try to remove it
696 * without it having been added, which DBusLoop doesn't allow */
697 _dbus_watch_invalidate (sitter->sitter_watch);
698 _dbus_watch_unref (sitter->sitter_watch);
699 sitter->sitter_watch = NULL;
701 _DBUS_SET_OOM (error);
705 sitter->argc = protect_argv (argv, &sitter->argv);
706 if (sitter->argc == -1)
708 _DBUS_SET_OOM (error);
714 sitter_thread = (HANDLE) CreateThread (NULL, 0, babysitter,
715 sitter, 0, &sitter_thread_id);
717 if (sitter_thread == 0)
720 dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
721 "Failed to create new thread");
724 CloseHandle (sitter_thread);
727 WaitForSingleObject (sitter->start_sync_event, INFINITE);
730 if (sitter_p != NULL)
733 _dbus_babysitter_unref (sitter);
735 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
741 _dbus_babysitter_unref (sitter);
747 _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
748 DBusBabysitterFinishedFunc finished,
751 sitter->finished_cb = finished;
752 sitter->finished_data = user_data;
755 #ifdef DBUS_BUILD_TESTS
758 get_test_exec (const char *exe,
759 DBusString *scratch_space)
761 const char *dbus_test_exec;
763 dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
765 if (dbus_test_exec == NULL)
766 dbus_test_exec = DBUS_TEST_EXEC;
768 if (!_dbus_string_init (scratch_space))
771 if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
772 dbus_test_exec, exe, DBUS_EXEEXT))
774 _dbus_string_free (scratch_space);
778 return _dbus_string_get_data (scratch_space);
781 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
784 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
786 if (sitter->child_handle == NULL)
789 WaitForSingleObject (sitter->end_sync_event, INFINITE);
793 check_spawn_nonexistent (void *data)
795 char *argv[4] = { NULL, NULL, NULL, NULL };
796 DBusBabysitter *sitter;
801 dbus_error_init (&error);
803 /*** Test launching nonexistent binary */
805 argv[0] = "/this/does/not/exist/32542sdgafgafdg";
806 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
810 _dbus_babysitter_block_for_child_exit (sitter);
811 _dbus_babysitter_set_child_exit_error (sitter, &error);
815 _dbus_babysitter_unref (sitter);
817 if (!dbus_error_is_set (&error))
819 _dbus_warn ("Did not get an error launching nonexistent executable\n");
823 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
824 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
826 _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
827 error.name, error.message);
828 dbus_error_free (&error);
832 dbus_error_free (&error);
838 check_spawn_segfault (void *data)
840 char *argv[4] = { NULL, NULL, NULL, NULL };
841 DBusBabysitter *sitter;
847 dbus_error_init (&error);
849 /*** Test launching segfault binary */
851 argv[0] = get_test_exec ("test-segfault", &argv0);
855 /* OOM was simulated, never mind */
859 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
863 _dbus_babysitter_block_for_child_exit (sitter);
864 _dbus_babysitter_set_child_exit_error (sitter, &error);
867 _dbus_string_free (&argv0);
870 _dbus_babysitter_unref (sitter);
872 if (!dbus_error_is_set (&error))
874 _dbus_warn ("Did not get an error launching segfaulting binary\n");
878 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
879 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
881 _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
882 error.name, error.message);
883 dbus_error_free (&error);
887 dbus_error_free (&error);
893 check_spawn_exit (void *data)
895 char *argv[4] = { NULL, NULL, NULL, NULL };
896 DBusBabysitter *sitter;
902 dbus_error_init (&error);
904 /*** Test launching exit failure binary */
906 argv[0] = get_test_exec ("test-exit", &argv0);
910 /* OOM was simulated, never mind */
914 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
918 _dbus_babysitter_block_for_child_exit (sitter);
919 _dbus_babysitter_set_child_exit_error (sitter, &error);
922 _dbus_string_free (&argv0);
925 _dbus_babysitter_unref (sitter);
927 if (!dbus_error_is_set (&error))
929 _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
933 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
934 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
936 _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
937 error.name, error.message);
938 dbus_error_free (&error);
942 dbus_error_free (&error);
948 check_spawn_and_kill (void *data)
950 char *argv[4] = { NULL, NULL, NULL, NULL };
951 DBusBabysitter *sitter;
957 dbus_error_init (&error);
959 /*** Test launching sleeping binary then killing it */
961 argv[0] = get_test_exec ("test-sleep-forever", &argv0);
965 /* OOM was simulated, never mind */
969 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
973 _dbus_babysitter_kill_child (sitter);
975 _dbus_babysitter_block_for_child_exit (sitter);
977 _dbus_babysitter_set_child_exit_error (sitter, &error);
980 _dbus_string_free (&argv0);
983 _dbus_babysitter_unref (sitter);
985 if (!dbus_error_is_set (&error))
987 _dbus_warn ("Did not get an error after killing spawned binary\n");
991 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
992 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
994 _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
995 error.name, error.message);
996 dbus_error_free (&error);
1000 dbus_error_free (&error);
1006 _dbus_spawn_test (const char *test_data_dir)
1008 if (!_dbus_test_oom_handling ("spawn_nonexistent",
1009 check_spawn_nonexistent,
1013 /* Don't run the obnoxious segfault test by default,
1014 * it's a pain to have to click all those error boxes.
1016 if (getenv ("DO_SEGFAULT_TEST"))
1017 if (!_dbus_test_oom_handling ("spawn_segfault",
1018 check_spawn_segfault,
1022 if (!_dbus_test_oom_handling ("spawn_exit",
1027 if (!_dbus_test_oom_handling ("spawn_and_kill",
1028 check_spawn_and_kill,