5 #if !defined(SPAWN_DEBUG) || defined(_MSC_VER)
8 #define PING() fprintf (stderr, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__); fflush (stderr)
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
65 HANDLE start_sync_event;
66 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
68 HANDLE end_sync_event;
72 DBusSpawnChildSetupFunc child_setup;
85 DBusBabysitterFinishedFunc finished_cb;
95 _dbus_babysitter_new (
void)
106 if (sitter->start_sync_event ==
NULL)
112 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
114 if (sitter->end_sync_event ==
NULL)
121 sitter->child_handle =
NULL;
136 sitter->have_spawn_errno =
FALSE;
137 sitter->have_child_status =
FALSE;
163 _dbus_verbose (
"Closing babysitter\n");
199 close_socket_to_babysitter (sitter);
201 if (sitter->socket_to_main != -1)
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)
214 sitter->argv[i] =
NULL;
220 if (sitter->envp !=
NULL)
222 char **e = sitter->envp;
230 if (sitter->child_handle !=
NULL)
232 CloseHandle (sitter->child_handle);
233 sitter->child_handle =
NULL;
246 if (sitter->start_sync_event !=
NULL)
249 CloseHandle (sitter->start_sync_event);
250 sitter->start_sync_event =
NULL;
253 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
254 if (sitter->end_sync_event !=
NULL)
256 CloseHandle (sitter->end_sync_event);
257 sitter->end_sync_event =
NULL;
271 if (sitter->child_handle ==
NULL)
275 TerminateProcess (sitter->child_handle, 12345);
287 return (sitter->child_handle ==
NULL);
309 if (!sitter->have_child_status ||
310 sitter->child_status == STILL_ACTIVE)
313 *status = sitter->child_status;
335 if (sitter->have_spawn_errno)
337 char *emsg = _dbus_win_error_string (sitter->spawn_errno);
339 "Failed to execute program %s: %s",
341 _dbus_win_free_error_string (emsg);
343 else if (sitter->have_child_status)
347 "Process %s exited with status %d",
348 sitter->
log_name, sitter->child_status);
354 "Process %s exited, status unknown",
379 unsigned int condition,
395 close_socket_to_babysitter (sitter);
399 sitter->finished_cb !=
NULL)
401 sitter->finished_cb (sitter, sitter->finished_data);
402 sitter->finished_cb =
NULL;
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;
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 ==
'\\')
492 (*new_argv)[argc] =
NULL;
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;
551 arg_string = build_commandline (argv + 1);
555 arg_string = build_commandline (argv);
558 return INVALID_HANDLE_VALUE;
560 env_string = build_env_string(envp);
562 memset (&si, 0,
sizeof (si));
565 result = CreateProcessA (name, arg_string,
NULL,
NULL,
FALSE, 0,
569 (LPVOID)env_string,
NULL, &si, &pi);
575 return INVALID_HANDLE_VALUE;
577 CloseHandle (pi.hThread);
582 static DWORD __stdcall
583 babysitter (
void *parameter)
590 if (sitter->child_setup)
593 (*sitter->child_setup) (sitter->user_data);
596 _dbus_verbose (
"babysitter: spawning %s\n", sitter->
log_name);
599 sitter->child_handle = spawn_program (sitter->
log_name,
600 sitter->argv, sitter->envp);
603 if (sitter->child_handle == (HANDLE) -1)
605 sitter->child_handle =
NULL;
606 sitter->have_spawn_errno =
TRUE;
607 sitter->spawn_errno = GetLastError();
611 SetEvent (sitter->start_sync_event);
613 if (sitter->child_handle !=
NULL)
619 WaitForSingleObject (sitter->child_handle, INFINITE);
622 ret = GetExitCodeProcess (sitter->child_handle, &status);
624 sitter->child_status = status;
625 sitter->have_child_status =
TRUE;
627 CloseHandle (sitter->child_handle);
628 sitter->child_handle =
NULL;
631 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
632 SetEvent (sitter->end_sync_event);
636 send (sitter->socket_to_main,
" ", 1, 0);
645 const char *log_name,
648 DBusSpawnChildSetupFunc child_setup,
653 HANDLE sitter_thread;
654 DWORD sitter_thread_id;
656 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
662 sitter = _dbus_babysitter_new ();
665 _DBUS_SET_OOM (error);
669 sitter->child_setup = child_setup;
670 sitter->user_data = user_data;
675 _DBUS_SET_OOM (error);
684 _DBUS_SET_OOM (error);
690 &sitter->socket_to_main,
700 _DBUS_SET_OOM (error);
713 _DBUS_SET_OOM (error);
717 sitter->argc = protect_argv (argv, &sitter->argv);
718 if (sitter->argc == -1)
720 _DBUS_SET_OOM (error);
726 sitter_thread = (HANDLE) CreateThread (
NULL, 0, babysitter,
727 sitter, 0, &sitter_thread_id);
729 if (sitter_thread == 0)
733 "Failed to create new thread");
736 CloseHandle (sitter_thread);
739 WaitForSingleObject (sitter->start_sync_event, INFINITE);
742 if (sitter_p !=
NULL)
747 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
760 DBusBabysitterFinishedFunc finished,
763 sitter->finished_cb = finished;
764 sitter->finished_data = user_data;
767 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
770 get_test_exec (
const char *exe,
773 const char *dbus_test_exec;
777 if (dbus_test_exec ==
NULL)
778 dbus_test_exec = DBUS_TEST_EXEC;
784 dbus_test_exec, exe, DBUS_EXEEXT))
790 return _dbus_string_get_data (scratch_space);
793 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
798 if (sitter->child_handle ==
NULL)
801 WaitForSingleObject (sitter->end_sync_event, INFINITE);
805 check_spawn_nonexistent (
void *data)
817 argv[0] =
"/this/does/not/exist/32542sdgafgafdg";
822 _dbus_babysitter_block_for_child_exit (sitter);
831 _dbus_warn (
"Did not get an error launching nonexistent executable\n");
838 _dbus_warn (
"Not expecting error when launching nonexistent executable: %s: %s\n",
850 check_spawn_segfault (
void *data)
863 argv[0] = get_test_exec (
"test-segfault", &argv0);
875 _dbus_babysitter_block_for_child_exit (sitter);
886 _dbus_warn (
"Did not get an error launching segfaulting binary\n");
893 _dbus_warn (
"Not expecting error when launching segfaulting executable: %s: %s\n",
905 check_spawn_exit (
void *data)
918 argv[0] = get_test_exec (
"test-exit", &argv0);
930 _dbus_babysitter_block_for_child_exit (sitter);
941 _dbus_warn (
"Did not get an error launching binary that exited with failure code\n");
948 _dbus_warn (
"Not expecting error when launching exiting executable: %s: %s\n",
960 check_spawn_and_kill (
void *data)
973 argv[0] = get_test_exec (
"test-sleep-forever", &argv0);
987 _dbus_babysitter_block_for_child_exit (sitter);
999 _dbus_warn (
"Did not get an error after killing spawned binary\n");
1006 _dbus_warn (
"Not expecting error when killing executable: %s: %s\n",
1018 _dbus_spawn_test (
const char *test_data_dir)
1020 if (!_dbus_test_oom_handling (
"spawn_nonexistent",
1021 check_spawn_nonexistent,
1028 if (getenv (
"DO_SEGFAULT_TEST"))
1029 if (!_dbus_test_oom_handling (
"spawn_segfault",
1030 check_spawn_segfault,
1034 if (!_dbus_test_oom_handling (
"spawn_exit",
1039 if (!_dbus_test_oom_handling (
"spawn_and_kill",
1040 check_spawn_and_kill,