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
64 HANDLE start_sync_event;
65 #ifdef DBUS_BUILD_TESTS
67 HANDLE end_sync_event;
71 DBusSpawnChildSetupFunc child_setup;
92 _dbus_babysitter_new (
void)
103 if (sitter->start_sync_event ==
NULL)
109 #ifdef DBUS_BUILD_TESTS
111 if (sitter->end_sync_event ==
NULL)
118 sitter->child_handle =
NULL;
133 sitter->have_spawn_errno =
FALSE;
134 sitter->have_child_status =
FALSE;
181 if (sitter->socket_to_main != -1)
184 sitter->socket_to_main = -1;
188 if (sitter->argv !=
NULL)
190 for (i = 0; i < sitter->argc; i++)
191 if (sitter->argv[i] !=
NULL)
194 sitter->argv[i] =
NULL;
200 if (sitter->envp !=
NULL)
202 char **e = sitter->envp;
210 if (sitter->child_handle !=
NULL)
212 CloseHandle (sitter->child_handle);
213 sitter->child_handle =
NULL;
226 if (sitter->start_sync_event !=
NULL)
229 CloseHandle (sitter->start_sync_event);
230 sitter->start_sync_event =
NULL;
233 #ifdef DBUS_BUILD_TESTS
234 if (sitter->end_sync_event !=
NULL)
236 CloseHandle (sitter->end_sync_event);
237 sitter->end_sync_event =
NULL;
251 if (sitter->child_handle ==
NULL)
255 TerminateProcess (sitter->child_handle, 12345);
267 return (sitter->child_handle ==
NULL);
289 if (!sitter->have_child_status ||
290 sitter->child_status == STILL_ACTIVE)
293 *status = sitter->child_status;
315 if (sitter->have_spawn_errno)
317 char *emsg = _dbus_win_error_string (sitter->spawn_errno);
319 "Failed to execute program %s: %s",
321 _dbus_win_free_error_string (emsg);
323 else if (sitter->have_child_status)
327 "Process %s exited with status %d",
334 "Process %s exited, status unknown",
359 unsigned int condition,
384 protect_argv (
char **argv,
392 *new_argv =
dbus_malloc ((argc + 1) *
sizeof (
char *));
393 if (*new_argv ==
NULL)
396 for (i = 0; i < argc; i++)
397 (*new_argv)[i] =
NULL;
410 for (i = 0; i < argc; i++)
415 int need_dblquotes =
FALSE;
418 if (*p ==
' ' || *p ==
'\t')
419 need_dblquotes =
TRUE;
425 while (*pp && *pp ==
'\\')
434 q = (*new_argv)[i] =
dbus_malloc (len + need_dblquotes*2 + 1);
452 while (*pp && *pp ==
'\\')
466 (*new_argv)[argc] =
NULL;
474 compose_string (
char **strings,
char separator)
482 if (!strings || !strings[0])
484 for (i = 0; strings[i]; i++)
485 n += strlen (strings[i]) + 1;
488 buf = p = malloc (n);
491 for (i = 0; strings[i]; i++)
493 strcpy (p, strings[i]);
494 p += strlen (strings[i]);
505 build_commandline (
char **argv)
507 return compose_string (argv,
' ');
511 build_env_string (
char** envp)
513 return compose_string (envp,
'\0');
517 spawn_program (
char* name,
char** argv,
char** envp)
519 PROCESS_INFORMATION pi = {
NULL, 0, 0, 0 };
521 char *arg_string, *env_string;
526 arg_string = build_commandline (argv + 1);
530 arg_string = build_commandline (argv);
533 return INVALID_HANDLE_VALUE;
535 env_string = build_env_string(envp);
537 memset (&si, 0,
sizeof (si));
540 result = CreateProcessA (name, arg_string,
NULL,
NULL,
FALSE, 0,
544 (LPVOID)env_string,
NULL, &si, &pi);
550 return INVALID_HANDLE_VALUE;
552 CloseHandle (pi.hThread);
557 static DWORD __stdcall
558 babysitter (
void *parameter)
565 if (sitter->child_setup)
568 (*sitter->child_setup) (sitter->user_data);
571 _dbus_verbose (
"babysitter: spawning %s\n", sitter->
executable);
574 sitter->child_handle = spawn_program (sitter->
executable,
575 sitter->argv, sitter->envp);
578 if (sitter->child_handle == (HANDLE) -1)
580 sitter->child_handle =
NULL;
581 sitter->have_spawn_errno =
TRUE;
582 sitter->spawn_errno = GetLastError();
586 SetEvent (sitter->start_sync_event);
588 if (sitter->child_handle !=
NULL)
594 WaitForSingleObject (sitter->child_handle, INFINITE);
597 ret = GetExitCodeProcess (sitter->child_handle, &status);
599 sitter->child_status = status;
600 sitter->have_child_status =
TRUE;
602 CloseHandle (sitter->child_handle);
603 sitter->child_handle =
NULL;
606 #ifdef DBUS_BUILD_TESTS
607 SetEvent (sitter->end_sync_event);
611 send (sitter->socket_to_main,
" ", 1, 0);
622 DBusSpawnChildSetupFunc child_setup,
627 HANDLE sitter_thread;
628 DWORD sitter_thread_id;
630 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
635 sitter = _dbus_babysitter_new ();
638 _DBUS_SET_OOM (error);
642 sitter->child_setup = child_setup;
643 sitter->user_data = user_data;
648 _DBUS_SET_OOM (error);
654 &sitter->socket_to_main,
664 _DBUS_SET_OOM (error);
671 _DBUS_SET_OOM (error);
675 sitter->argc = protect_argv (argv, &sitter->argv);
676 if (sitter->argc == -1)
678 _DBUS_SET_OOM (error);
684 sitter_thread = (HANDLE) CreateThread (
NULL, 0, babysitter,
685 sitter, 0, &sitter_thread_id);
687 if (sitter_thread == 0)
691 "Failed to create new thread");
694 CloseHandle (sitter_thread);
697 WaitForSingleObject (sitter->start_sync_event, INFINITE);
700 if (sitter_p !=
NULL)
705 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
716 #ifdef DBUS_BUILD_TESTS
718 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
723 if (sitter->child_handle ==
NULL)
726 WaitForSingleObject (sitter->end_sync_event, INFINITE);
730 check_spawn_nonexistent (
void *data)
742 argv[0] =
"/this/does/not/exist/32542sdgafgafdg";
747 _dbus_babysitter_block_for_child_exit (sitter);
756 _dbus_warn (
"Did not get an error launching nonexistent executable\n");
763 _dbus_warn (
"Not expecting error when launching nonexistent executable: %s: %s\n",
775 check_spawn_segfault (
void *data)
787 argv[0] = TEST_SEGFAULT_BINARY;
792 _dbus_babysitter_block_for_child_exit (sitter);
801 _dbus_warn (
"Did not get an error launching segfaulting binary\n");
808 _dbus_warn (
"Not expecting error when launching segfaulting executable: %s: %s\n",
820 check_spawn_exit (
void *data)
832 argv[0] = TEST_EXIT_BINARY;
837 _dbus_babysitter_block_for_child_exit (sitter);
846 _dbus_warn (
"Did not get an error launching binary that exited with failure code\n");
853 _dbus_warn (
"Not expecting error when launching exiting executable: %s: %s\n",
865 check_spawn_and_kill (
void *data)
877 argv[0] = TEST_SLEEP_FOREVER_BINARY;
884 _dbus_babysitter_block_for_child_exit (sitter);
894 _dbus_warn (
"Did not get an error after killing spawned binary\n");
901 _dbus_warn (
"Not expecting error when killing executable: %s: %s\n",
913 _dbus_spawn_test (
const char *test_data_dir)
915 if (!_dbus_test_oom_handling (
"spawn_nonexistent",
916 check_spawn_nonexistent,
923 if (getenv (
"DO_SEGFAULT_TEST"))
924 if (!_dbus_test_oom_handling (
"spawn_segfault",
925 check_spawn_segfault,
929 if (!_dbus_test_oom_handling (
"spawn_exit",
934 if (!_dbus_test_oom_handling (
"spawn_and_kill",
935 check_spawn_and_kill,