#include "dbus-protocol.h"
#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
//#define STRICT
//#include <windows.h>
//#undef STRICT
DBusWatchList *watches;
DBusWatch *sitter_watch;
+ DBusBabysitterFinishedFunc finished_cb;
+ void *finished_data;
dbus_bool_t have_spawn_errno;
int spawn_errno;
return sitter;
}
+static void
+close_socket_to_babysitter (DBusBabysitter *sitter)
+{
+ _dbus_verbose ("Closing babysitter\n");
+
+ if (sitter->sitter_watch != NULL)
+ {
+ _dbus_assert (sitter->watches != NULL);
+ _dbus_watch_list_remove_watch (sitter->watches, sitter->sitter_watch);
+ _dbus_watch_invalidate (sitter->sitter_watch);
+ _dbus_watch_unref (sitter->sitter_watch);
+ sitter->sitter_watch = NULL;
+ }
+
+ if (sitter->socket_to_babysitter != -1)
+ {
+ _dbus_close_socket (sitter->socket_to_babysitter, NULL);
+ sitter->socket_to_babysitter = -1;
+ }
+}
+
/**
* Decrement the reference count on the babysitter object.
*
if (sitter->refcount == 0)
{
- if (sitter->socket_to_babysitter != -1)
- {
- _dbus_close_socket (sitter->socket_to_babysitter, NULL);
- sitter->socket_to_babysitter = -1;
- }
+ close_socket_to_babysitter (sitter);
if (sitter->socket_to_main != -1)
{
*/
PING();
- _dbus_close_socket (sitter->socket_to_babysitter, NULL);
+ close_socket_to_babysitter (sitter);
PING();
- sitter->socket_to_babysitter = -1;
+
+ if (_dbus_babysitter_get_child_exited (sitter) &&
+ sitter->finished_cb != NULL)
+ {
+ sitter->finished_cb (sitter, sitter->finished_data);
+ sitter->finished_cb = NULL;
+ }
return TRUE;
}
/* From GPGME, relicensed by g10 Code GmbH. */
static char *
-build_commandline (char **argv)
+compose_string (char **strings, char separator)
{
int i;
int n = 0;
char *buf;
char *p;
- const char *ptr;
-
- for (i = 0; argv[i]; i++)
- n += strlen (argv[i]) + 1;
+
+ if (!strings || !strings[0])
+ return 0;
+ for (i = 0; strings[i]; i++)
+ n += strlen (strings[i]) + 1;
n++;
buf = p = malloc (n);
if (!buf)
return NULL;
- for (i = 0; argv[i]; i++)
+ for (i = 0; strings[i]; i++)
{
- strcpy (p, argv[i]);
- p += strlen (argv[i]);
- *(p++) = ' ';
+ strcpy (p, strings[i]);
+ p += strlen (strings[i]);
+ *(p++) = separator;
}
- if (i)
- p--;
+ p--;
+ *(p++) = '\0';
*p = '\0';
return buf;
}
+static char *
+build_commandline (char **argv)
+{
+ return compose_string (argv, ' ');
+}
+
+static char *
+build_env_string (char** envp)
+{
+ return compose_string (envp, '\0');
+}
static HANDLE
-spawn_program (const char* name, char** argv, char** envp)
+spawn_program (char* name, char** argv, char** envp)
{
PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
STARTUPINFOA si;
- char *arg_string;
+ char *arg_string, *env_string;
BOOL result;
#ifdef DBUS_WINCE
- arg_string = build_commandline (argv + 1);
+ if (argv && argv[0])
+ arg_string = build_commandline (argv + 1);
+ else
+ arg_string = NULL;
#else
arg_string = build_commandline (argv);
#endif
if (!arg_string)
return INVALID_HANDLE_VALUE;
+ env_string = build_env_string(envp);
+
memset (&si, 0, sizeof (si));
si.cb = sizeof (si);
+#ifdef DBUS_WINCE
result = CreateProcessA (name, arg_string, NULL, NULL, FALSE, 0,
- envp, NULL, &si, &pi);
+#else
+ result = CreateProcessA (NULL, arg_string, NULL, NULL, FALSE, 0,
+#endif
+ (LPVOID)env_string, NULL, &si, &pi);
free (arg_string);
+ if (env_string)
+ free (env_string);
+
if (!result)
return INVALID_HANDLE_VALUE;
babysitter (void *parameter)
{
DBusBabysitter *sitter = (DBusBabysitter *) parameter;
- int fd;
+
PING();
_dbus_babysitter_ref (sitter);
PING();
if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
{
+ /* we need to free it early so the destructor won't try to remove it
+ * without it having been added, which DBusLoop doesn't allow */
+ _dbus_watch_invalidate (sitter->sitter_watch);
+ _dbus_watch_unref (sitter->sitter_watch);
+ sitter->sitter_watch = NULL;
+
_DBUS_SET_OOM (error);
goto out0;
}
return FALSE;
}
+void
+_dbus_babysitter_set_result_function (DBusBabysitter *sitter,
+ DBusBabysitterFinishedFunc finished,
+ void *user_data)
+{
+ sitter->finished_cb = finished;
+ sitter->finished_data = user_data;
+}
+
#ifdef DBUS_BUILD_TESTS
+static char *
+get_test_exec (const char *exe,
+ DBusString *scratch_space)
+{
+ const char *dbus_test_exec;
+
+ dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
+
+ if (dbus_test_exec == NULL)
+ dbus_test_exec = DBUS_TEST_EXEC;
+
+ if (!_dbus_string_init (scratch_space))
+ return NULL;
+
+ if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
+ dbus_test_exec, exe, DBUS_EXEEXT))
+ {
+ _dbus_string_free (scratch_space);
+ return NULL;
+ }
+
+ return _dbus_string_get_data (scratch_space);
+}
+
#define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
static void
char *argv[4] = { NULL, NULL, NULL, NULL };
DBusBabysitter *sitter;
DBusError error;
+ DBusString argv0;
sitter = NULL;
/*** Test launching segfault binary */
- argv[0] = TEST_SEGFAULT_BINARY;
+ argv[0] = get_test_exec ("test-segfault", &argv0);
+
+ if (argv[0] == NULL)
+ {
+ /* OOM was simulated, never mind */
+ return TRUE;
+ }
+
if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
NULL, NULL,
&error))
_dbus_babysitter_set_child_exit_error (sitter, &error);
}
+ _dbus_string_free (&argv0);
+
if (sitter)
_dbus_babysitter_unref (sitter);
char *argv[4] = { NULL, NULL, NULL, NULL };
DBusBabysitter *sitter;
DBusError error;
+ DBusString argv0;
sitter = NULL;
/*** Test launching exit failure binary */
- argv[0] = TEST_EXIT_BINARY;
+ argv[0] = get_test_exec ("test-exit", &argv0);
+
+ if (argv[0] == NULL)
+ {
+ /* OOM was simulated, never mind */
+ return TRUE;
+ }
+
if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
NULL, NULL,
&error))
_dbus_babysitter_set_child_exit_error (sitter, &error);
}
+ _dbus_string_free (&argv0);
+
if (sitter)
_dbus_babysitter_unref (sitter);
char *argv[4] = { NULL, NULL, NULL, NULL };
DBusBabysitter *sitter;
DBusError error;
+ DBusString argv0;
sitter = NULL;
/*** Test launching sleeping binary then killing it */
- argv[0] = TEST_SLEEP_FOREVER_BINARY;
+ argv[0] = get_test_exec ("test-sleep-forever", &argv0);
+
+ if (argv[0] == NULL)
+ {
+ /* OOM was simulated, never mind */
+ return TRUE;
+ }
+
if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
NULL, NULL,
&error))
_dbus_babysitter_set_child_exit_error (sitter, &error);
}
+ _dbus_string_free (&argv0);
+
if (sitter)
_dbus_babysitter_unref (sitter);