3 #if !defined(DBUS_ENABLE_VERBOSE_MODE) || defined(_MSC_VER)
6 #define PING() fprintf (stderr, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__); fflush (stderr)
14 /* -*- mode: C; c-file-style: "gnu" -*- */
15 /* dbus-spawn-win32.c Wrapper around g_spawn
17 * Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
18 * Copyright (C) 2003 CodeFactory AB
19 * Copyright (C) 2005 Novell, Inc.
21 * Licensed under the Academic Free License version 2.1
23 * This program is free software; you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published by
25 * the Free Software Foundation; either version 2 of the License, or
26 * (at your option) any later version.
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 #include "dbus-spawn.h"
39 #include "dbus-sysdeps.h"
40 #include "dbus-sysdeps-win.h"
41 #include "dbus-internals.h"
42 #include "dbus-test.h"
43 #include "dbus-protocol.h"
45 #define WIN32_LEAN_AND_MEAN
47 //#include <windows.h>
57 * Babysitter implementation details
63 HANDLE start_sync_event;
64 #ifdef DBUS_BUILD_TESTS
66 HANDLE end_sync_event;
70 DBusSpawnChildSetupFunc child_setup;
78 int socket_to_babysitter; /* Connection to the babysitter thread */
81 DBusWatchList *watches;
82 DBusWatch *sitter_watch;
84 dbus_bool_t have_spawn_errno;
86 dbus_bool_t have_child_status;
90 static DBusBabysitter*
91 _dbus_babysitter_new (void)
93 DBusBabysitter *sitter;
95 sitter = dbus_new0 (DBusBabysitter, 1);
101 sitter->start_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
102 if (sitter->start_sync_event == NULL)
104 _dbus_babysitter_unref (sitter);
108 #ifdef DBUS_BUILD_TESTS
109 sitter->end_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
110 if (sitter->end_sync_event == NULL)
112 _dbus_babysitter_unref (sitter);
117 sitter->child_handle = NULL;
119 sitter->socket_to_babysitter = sitter->socket_to_main = -1;
125 sitter->watches = _dbus_watch_list_new ();
126 if (sitter->watches == NULL)
128 _dbus_babysitter_unref (sitter);
132 sitter->have_spawn_errno = FALSE;
133 sitter->have_child_status = FALSE;
139 * Increment the reference count on the babysitter object.
141 * @param sitter the babysitter
142 * @returns the babysitter
145 _dbus_babysitter_ref (DBusBabysitter *sitter)
148 _dbus_assert (sitter != NULL);
149 _dbus_assert (sitter->refcount > 0);
151 sitter->refcount += 1;
157 * Decrement the reference count on the babysitter object.
159 * @param sitter the babysitter
162 _dbus_babysitter_unref (DBusBabysitter *sitter)
167 _dbus_assert (sitter != NULL);
168 _dbus_assert (sitter->refcount > 0);
170 sitter->refcount -= 1;
172 if (sitter->refcount == 0)
174 if (sitter->socket_to_babysitter != -1)
176 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
177 sitter->socket_to_babysitter = -1;
180 if (sitter->socket_to_main != -1)
182 _dbus_close_socket (sitter->socket_to_main, NULL);
183 sitter->socket_to_main = -1;
187 if (sitter->argv != NULL)
189 for (i = 0; i < sitter->argc; i++)
190 if (sitter->argv[i] != NULL)
192 dbus_free (sitter->argv[i]);
193 sitter->argv[i] = NULL;
195 dbus_free (sitter->argv);
199 if (sitter->envp != NULL)
201 char **e = sitter->envp;
205 dbus_free (sitter->envp);
209 if (sitter->child_handle != NULL)
211 CloseHandle (sitter->child_handle);
212 sitter->child_handle = NULL;
215 if (sitter->sitter_watch)
217 _dbus_watch_invalidate (sitter->sitter_watch);
218 _dbus_watch_unref (sitter->sitter_watch);
219 sitter->sitter_watch = NULL;
223 _dbus_watch_list_free (sitter->watches);
225 if (sitter->start_sync_event != NULL)
228 CloseHandle (sitter->start_sync_event);
229 sitter->end_sync_event = NULL;
232 #ifdef DBUS_BUILD_TESTS
233 if (sitter->end_sync_event != NULL)
235 CloseHandle (sitter->end_sync_event);
236 sitter->end_sync_event = NULL;
240 dbus_free (sitter->executable);
247 _dbus_babysitter_kill_child (DBusBabysitter *sitter)
250 if (sitter->child_handle == NULL)
251 return; /* child is already dead, or we're so hosed we'll never recover */
254 TerminateProcess (sitter->child_handle, 12345);
258 * Checks whether the child has exited, without blocking.
260 * @param sitter the babysitter
263 _dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
266 return (sitter->child_handle == NULL);
270 * Sets the #DBusError with an explanation of why the spawned
271 * child process exited (on a signal, or whatever). If
272 * the child process has not exited, does nothing (error
273 * will remain unset).
275 * @param sitter the babysitter
276 * @param error an error to fill in
279 _dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
283 if (!_dbus_babysitter_get_child_exited (sitter))
287 if (sitter->have_spawn_errno)
289 dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
290 "Failed to execute program %s: %s",
291 sitter->executable, _dbus_strerror (sitter->spawn_errno));
293 else if (sitter->have_child_status)
296 dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
297 "Process %s exited with status %d",
298 sitter->executable, sitter->child_status);
303 dbus_set_error (error, DBUS_ERROR_FAILED,
304 "Process %s exited, status unknown",
311 _dbus_babysitter_set_watch_functions (DBusBabysitter *sitter,
312 DBusAddWatchFunction add_function,
313 DBusRemoveWatchFunction remove_function,
314 DBusWatchToggledFunction toggled_function,
316 DBusFreeFunction free_data_function)
319 return _dbus_watch_list_set_functions (sitter->watches,
328 handle_watch (DBusWatch *watch,
329 unsigned int condition,
332 DBusBabysitter *sitter = data;
334 /* On Unix dbus-spawn uses a babysitter *process*, thus it has to
335 * actually send the exit statuses, error codes and whatnot through
336 * sockets and/or pipes. On Win32, the babysitter is jus a thread,
337 * so it can set the status fields directly in the babysitter struct
338 * just fine. The socket pipe is used just so we can watch it with
339 * select(), as soon as anything is written to it we know that the
340 * babysitter thread has recorded the status in the babysitter
345 _dbus_close_socket (sitter->socket_to_babysitter, NULL);
347 sitter->socket_to_babysitter = -1;
352 /* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
354 protect_argv (char **argv,
362 *new_argv = dbus_malloc ((argc + 1) * sizeof (char *));
363 if (*new_argv == NULL)
366 for (i = 0; i < argc; i++)
367 (*new_argv)[i] = NULL;
369 /* Quote each argv element if necessary, so that it will get
370 * reconstructed correctly in the C runtime startup code. Note that
371 * the unquoting algorithm in the C runtime is really weird, and
372 * rather different than what Unix shells do. See stdargv.c in the C
373 * runtime sources (in the Platform SDK, in src/crt).
375 * Note that an new_argv[0] constructed by this function should
376 * *not* be passed as the filename argument to a spawn* or exec*
377 * family function. That argument should be the real file name
378 * without any quoting.
380 for (i = 0; i < argc; i++)
385 int need_dblquotes = FALSE;
388 if (*p == ' ' || *p == '\t')
389 need_dblquotes = TRUE;
395 while (*pp && *pp == '\\')
404 q = (*new_argv)[i] = dbus_malloc (len + need_dblquotes*2 + 1);
422 while (*pp && *pp == '\\')
434 /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (*new_argv)[i]); */
436 (*new_argv)[argc] = NULL;
441 static unsigned __stdcall
442 babysitter (void *parameter)
444 DBusBabysitter *sitter = (DBusBabysitter *) parameter;
447 _dbus_babysitter_ref (sitter);
449 if (sitter->child_setup)
452 (*sitter->child_setup) (sitter->user_data);
455 _dbus_verbose ("babysitter: spawning %s\n", sitter->executable);
456 fprintf (stderr, "babysitter: spawning %s\n", sitter->executable);
459 if (sitter->envp != NULL)
460 sitter->child_handle = (HANDLE) spawnve (P_NOWAIT, sitter->executable,
461 (const char * const *) sitter->argv,
462 (const char * const *) sitter->envp);
464 sitter->child_handle = (HANDLE) spawnv (P_NOWAIT, sitter->executable,
465 (const char * const *) sitter->argv);
468 if (sitter->child_handle == (HANDLE) -1)
470 sitter->child_handle = NULL;
471 sitter->have_spawn_errno = TRUE;
472 sitter->spawn_errno = errno;
476 SetEvent (sitter->start_sync_event);
478 if (sitter->child_handle != NULL)
484 WaitForSingleObject (sitter->child_handle, INFINITE);
487 ret = GetExitCodeProcess (sitter->child_handle, &status);
489 sitter->child_status = status;
490 sitter->have_child_status = TRUE;
492 CloseHandle (sitter->child_handle);
493 sitter->child_handle = NULL;
496 #ifdef DBUS_BUILD_TESTS
497 SetEvent (sitter->end_sync_event);
501 _dbus_handle_to_socket (sitter->socket_to_main, &sock);
502 send (sock->fd, " ", 1, 0);
504 _dbus_babysitter_unref (sitter);
510 _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
513 DBusSpawnChildSetupFunc child_setup,
517 DBusBabysitter *sitter;
518 HANDLE sitter_thread;
519 int sitter_thread_id;
521 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
526 sitter = _dbus_babysitter_new ();
529 _DBUS_SET_OOM (error);
533 sitter->child_setup = child_setup;
534 sitter->user_data = user_data;
536 sitter->executable = _dbus_strdup (argv[0]);
537 if (sitter->executable == NULL)
539 _DBUS_SET_OOM (error);
544 if (!_dbus_full_duplex_pipe (&sitter->socket_to_babysitter,
545 &sitter->socket_to_main,
549 sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter,
551 TRUE, handle_watch, sitter, NULL);
553 if (sitter->sitter_watch == NULL)
555 _DBUS_SET_OOM (error);
560 if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
562 _DBUS_SET_OOM (error);
566 sitter->argc = protect_argv (argv, &sitter->argv);
567 if (sitter->argc == -1)
569 _DBUS_SET_OOM (error);
575 sitter_thread = (HANDLE) _beginthreadex (NULL, 0, babysitter,
576 sitter, 0, &sitter_thread_id);
578 if (sitter_thread == 0)
581 dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
582 "Failed to create new thread");
585 CloseHandle (sitter_thread);
588 WaitForSingleObject (sitter->start_sync_event, INFINITE);
591 if (sitter_p != NULL)
594 _dbus_babysitter_unref (sitter);
596 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
602 _dbus_babysitter_unref (sitter);
607 #ifdef DBUS_BUILD_TESTS
609 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
612 _dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
614 if (sitter->child_handle == NULL)
617 WaitForSingleObject (sitter->end_sync_event, INFINITE);
621 check_spawn_nonexistent (void *data)
623 char *argv[4] = { NULL, NULL, NULL, NULL };
624 DBusBabysitter *sitter;
629 dbus_error_init (&error);
631 /*** Test launching nonexistent binary */
633 argv[0] = "/this/does/not/exist/32542sdgafgafdg";
634 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
638 _dbus_babysitter_block_for_child_exit (sitter);
639 _dbus_babysitter_set_child_exit_error (sitter, &error);
643 _dbus_babysitter_unref (sitter);
645 if (!dbus_error_is_set (&error))
647 _dbus_warn ("Did not get an error launching nonexistent executable\n");
651 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
652 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
654 _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
655 error.name, error.message);
656 dbus_error_free (&error);
660 dbus_error_free (&error);
666 check_spawn_segfault (void *data)
668 char *argv[4] = { NULL, NULL, NULL, NULL };
669 DBusBabysitter *sitter;
674 dbus_error_init (&error);
676 /*** Test launching segfault binary */
678 argv[0] = TEST_SEGFAULT_BINARY;
679 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
683 _dbus_babysitter_block_for_child_exit (sitter);
684 _dbus_babysitter_set_child_exit_error (sitter, &error);
688 _dbus_babysitter_unref (sitter);
690 if (!dbus_error_is_set (&error))
692 _dbus_warn ("Did not get an error launching segfaulting binary\n");
696 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
697 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
699 _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
700 error.name, error.message);
701 dbus_error_free (&error);
705 dbus_error_free (&error);
711 check_spawn_exit (void *data)
713 char *argv[4] = { NULL, NULL, NULL, NULL };
714 DBusBabysitter *sitter;
719 dbus_error_init (&error);
721 /*** Test launching exit failure binary */
723 argv[0] = TEST_EXIT_BINARY;
724 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
728 _dbus_babysitter_block_for_child_exit (sitter);
729 _dbus_babysitter_set_child_exit_error (sitter, &error);
733 _dbus_babysitter_unref (sitter);
735 if (!dbus_error_is_set (&error))
737 _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
741 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
742 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
744 _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
745 error.name, error.message);
746 dbus_error_free (&error);
750 dbus_error_free (&error);
756 check_spawn_and_kill (void *data)
758 char *argv[4] = { NULL, NULL, NULL, NULL };
759 DBusBabysitter *sitter;
764 dbus_error_init (&error);
766 /*** Test launching sleeping binary then killing it */
768 argv[0] = TEST_SLEEP_FOREVER_BINARY;
769 if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
773 _dbus_babysitter_kill_child (sitter);
775 _dbus_babysitter_block_for_child_exit (sitter);
777 _dbus_babysitter_set_child_exit_error (sitter, &error);
781 _dbus_babysitter_unref (sitter);
783 if (!dbus_error_is_set (&error))
785 _dbus_warn ("Did not get an error after killing spawned binary\n");
789 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
790 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
792 _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
793 error.name, error.message);
794 dbus_error_free (&error);
798 dbus_error_free (&error);
804 _dbus_spawn_test (const char *test_data_dir)
806 if (!_dbus_test_oom_handling ("spawn_nonexistent",
807 check_spawn_nonexistent,
811 /* Don't run the obnoxious segfault test by default,
812 * it's a pain to have to click all those error boxes.
814 if (getenv ("DO_SEGFAULT_TEST"))
815 if (!_dbus_test_oom_handling ("spawn_segfault",
816 check_spawn_segfault,
820 if (!_dbus_test_oom_handling ("spawn_exit",
825 if (!_dbus_test_oom_handling ("spawn_and_kill",
826 check_spawn_and_kill,