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;
80 DBusBabysitterFinishedFunc finished_cb;
95 #ifdef DBUS_ENABLE_VERBOSE_MODE
96 static int enabled = -1;
98 _dbus_trace_ref (
"DBusBabysitter", sitter, old_refcount, new_refcount, why,
99 "DBUS_BABYSITTER_TRACE", &enabled);
104 _dbus_babysitter_new (
void)
115 _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, __FUNCTION__);
118 if (sitter->start_sync_event ==
NULL)
124 sitter->child_handle =
NULL;
139 sitter->have_spawn_errno =
FALSE;
140 sitter->have_child_status =
FALSE;
160 _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, __FUNCTION__);
168 _dbus_verbose (
"Closing babysitter\n");
202 _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount-1, __FUNCTION__);
204 if (old_refcount == 1)
206 close_socket_to_babysitter (sitter);
208 if (sitter->socket_to_main.sock != INVALID_SOCKET)
211 sitter->socket_to_main.sock = INVALID_SOCKET;
215 if (sitter->argv !=
NULL)
217 for (i = 0; i < sitter->argc; i++)
218 if (sitter->argv[i] !=
NULL)
221 sitter->argv[i] =
NULL;
227 if (sitter->envp !=
NULL)
229 char **e = sitter->envp;
237 if (sitter->child_handle !=
NULL)
239 CloseHandle (sitter->child_handle);
240 sitter->child_handle =
NULL;
253 if (sitter->start_sync_event !=
NULL)
256 CloseHandle (sitter->start_sync_event);
257 sitter->start_sync_event =
NULL;
260 if (sitter->thread_handle)
262 CloseHandle (sitter->thread_handle);
263 sitter->thread_handle =
NULL;
276 if (sitter->child_handle ==
NULL)
280 TerminateProcess (sitter->child_handle, 12345);
292 return (sitter->child_handle ==
NULL);
314 if (!sitter->have_child_status ||
315 sitter->child_status == STILL_ACTIVE)
318 *status = sitter->child_status;
340 if (sitter->have_spawn_errno)
342 char *emsg = _dbus_win_error_string (sitter->spawn_errno);
344 "Failed to execute program %s: %s",
346 _dbus_win_free_error_string (emsg);
348 else if (sitter->have_child_status)
352 "Process %s exited with status %d",
353 sitter->
log_name, sitter->child_status);
359 "Process %s exited, status unknown",
384 unsigned int condition,
400 close_socket_to_babysitter (sitter);
404 sitter->finished_cb !=
NULL)
406 sitter->finished_cb (sitter, sitter->finished_data);
407 sitter->finished_cb =
NULL;
415 protect_argv (
char *
const *argv,
423 *new_argv =
dbus_malloc ((argc + 1) *
sizeof (
char *));
424 if (*new_argv ==
NULL)
427 for (i = 0; i < argc; i++)
428 (*new_argv)[i] =
NULL;
441 for (i = 0; i < argc; i++)
443 const char *p = argv[i];
446 int need_dblquotes =
FALSE;
449 if (*p ==
' ' || *p ==
'\t')
450 need_dblquotes =
TRUE;
456 while (*pp && *pp ==
'\\')
465 q = (*new_argv)[i] =
dbus_malloc (len + need_dblquotes*2 + 1);
483 while (*pp && *pp ==
'\\')
497 (*new_argv)[argc] =
NULL;
505 compose_string (
char **strings,
char separator)
512 if (!strings || !strings[0])
514 for (i = 0; strings[i]; i++)
515 n += strlen (strings[i]) + 1;
518 buf = p = malloc (n);
521 for (i = 0; strings[i]; i++)
523 strcpy (p, strings[i]);
524 p += strlen (strings[i]);
535 build_commandline (
char **argv)
537 return compose_string (argv,
' ');
541 build_env_string (
char** envp)
543 return compose_string (envp,
'\0');
547 spawn_program (
char* name,
char** argv,
char** envp)
549 PROCESS_INFORMATION pi = {
NULL, 0, 0, 0 };
551 char *arg_string, *env_string;
556 arg_string = build_commandline (argv + 1);
560 arg_string = build_commandline (argv);
563 return INVALID_HANDLE_VALUE;
565 env_string = build_env_string(envp);
567 memset (&si, 0,
sizeof (si));
570 result = CreateProcessA (name, arg_string,
NULL,
NULL,
FALSE, 0,
574 (LPVOID)env_string,
NULL, &si, &pi);
580 return INVALID_HANDLE_VALUE;
582 CloseHandle (pi.hThread);
587 static DWORD __stdcall
588 babysitter (
void *parameter)
595 _dbus_verbose (
"babysitter: spawning %s\n", sitter->
log_name);
598 handle = spawn_program (sitter->
log_name, sitter->argv, sitter->envp);
601 if (handle != INVALID_HANDLE_VALUE)
603 sitter->child_handle = handle;
607 sitter->child_handle =
NULL;
608 sitter->have_spawn_errno =
TRUE;
609 sitter->spawn_errno = GetLastError();
613 SetEvent (sitter->start_sync_event);
615 if (sitter->child_handle !=
NULL)
621 WaitForSingleObject (sitter->child_handle, INFINITE);
624 ret = GetExitCodeProcess (sitter->child_handle, &status);
627 sitter->child_status = status;
628 sitter->have_child_status =
TRUE;
631 CloseHandle (sitter->child_handle);
632 sitter->child_handle =
NULL;
636 send (sitter->socket_to_main.sock,
" ", 1, 0);
645 const char *log_name,
648 DBusSpawnFlags flags _DBUS_GNUC_UNUSED,
649 DBusSpawnChildSetupFunc child_setup _DBUS_GNUC_UNUSED,
650 void *user_data _DBUS_GNUC_UNUSED,
654 DWORD sitter_thread_id;
656 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
659 if (sitter_p !=
NULL)
663 sitter = _dbus_babysitter_new ();
666 _DBUS_SET_OOM (error);
673 _DBUS_SET_OOM (error);
682 _DBUS_SET_OOM (error);
688 &sitter->socket_to_main,
698 _DBUS_SET_OOM (error);
711 _DBUS_SET_OOM (error);
715 sitter->argc = protect_argv (argv, &sitter->argv);
716 if (sitter->argc == -1)
718 _DBUS_SET_OOM (error);
724 sitter->thread_handle = (HANDLE) CreateThread (
NULL, 0, babysitter,
727 if (sitter->thread_handle ==
NULL)
731 "Failed to create new thread");
736 WaitForSingleObject (sitter->start_sync_event, INFINITE);
739 if (sitter_p !=
NULL)
744 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
757 DBusBabysitterFinishedFunc finished,
760 sitter->finished_cb = finished;
761 sitter->finished_data = user_data;
764 #define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
772 WaitForSingleObject (sitter->thread_handle, INFINITE);