dbus-spawn-win.c revision 70bfc74e54ac8a9a93885710cd8350d1a58b3406
170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include "config.h"
270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#if !defined(DBUS_ENABLE_VERBOSE_MODE) || defined(_MSC_VER)
470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#define PING()
570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#else
670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#define PING() fprintf (stderr, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__); fflush (stderr)
770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#endif
870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include <stdio.h>
1070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#ifdef DBUS_WINCE
1170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include <process.h>
1270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#endif
1370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
1470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/* -*- mode: C; c-file-style: "gnu" -*- */
1570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/* dbus-spawn-win32.c Wrapper around g_spawn
1670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
1770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Copyright (C) 2002, 2003, 2004  Red Hat, Inc.
1870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Copyright (C) 2003 CodeFactory AB
1970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Copyright (C) 2005 Novell, Inc.
2070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
2170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Licensed under the Academic Free License version 2.1
2270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
2370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * This program is free software; you can redistribute it and/or modify
2470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * it under the terms of the GNU General Public License as published by
2570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * the Free Software Foundation; either version 2 of the License, or
2670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * (at your option) any later version.
2770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
2870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * This program is distributed in the hope that it will be useful,
2970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * but WITHOUT ANY WARRANTY; without even the implied warranty of
3070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * GNU General Public License for more details.
3270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
3370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * You should have received a copy of the GNU General Public License
3470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * along with this program; if not, write to the Free Software
3570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
3670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
3770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker */
3870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include "dbus-spawn.h"
3970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include "dbus-sysdeps.h"
4070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include "dbus-sysdeps-win.h"
4170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include "dbus-internals.h"
4270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include "dbus-test.h"
4370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include "dbus-protocol.h"
4470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
4570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#define WIN32_LEAN_AND_MEAN
4670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker//#define STRICT
4770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker//#include <windows.h>
4870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker//#undef STRICT
4970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include <winsock2.h>
5070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#undef interface
5170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
5270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include <stdlib.h>
5370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
5470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#include <process.h>
5570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
5670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/**
5770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Babysitter implementation details
5870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker */
5970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstruct DBusBabysitter
6070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  {
6170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    int refcount;
6270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
6370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    HANDLE start_sync_event;
6470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#ifdef DBUS_BUILD_TESTS
6570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
6670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    HANDLE end_sync_event;
6770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#endif
6870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
6970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    char *executable;
7070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    DBusSpawnChildSetupFunc child_setup;
7170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    void *user_data;
7270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
7370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    int argc;
7470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    char **argv;
7570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    char **envp;
7670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
7770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    HANDLE child_handle;
7870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    int socket_to_babysitter;	/* Connection to the babysitter thread */
7970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    int socket_to_main;
8070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
8170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    DBusWatchList *watches;
8270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    DBusWatch *sitter_watch;
8370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
8470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    dbus_bool_t have_spawn_errno;
8570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    int spawn_errno;
8670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    dbus_bool_t have_child_status;
8770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    int child_status;
8870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  };
8970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
9070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic DBusBabysitter*
9170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_new (void)
9270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
9370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusBabysitter *sitter;
9470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
9570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter = dbus_new0 (DBusBabysitter, 1);
9670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter == NULL)
9770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return NULL;
9870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
9970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->refcount = 1;
10070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
10170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->start_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
10270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->start_sync_event == NULL)
10370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
10470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_unref (sitter);
10570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return NULL;
10670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
10770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
10870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#ifdef DBUS_BUILD_TESTS
10970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->end_sync_event = CreateEvent (NULL, FALSE, FALSE, NULL);
11070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->end_sync_event == NULL)
11170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
11270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_unref (sitter);
11370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return NULL;
11470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
11570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#endif
11670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
11770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->child_handle = NULL;
11870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
11970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->socket_to_babysitter = sitter->socket_to_main = -1;
12070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
12170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->argc = 0;
12270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->argv = NULL;
12370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->envp = NULL;
12470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
12570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->watches = _dbus_watch_list_new ();
12670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->watches == NULL)
12770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
12870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_unref (sitter);
12970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return NULL;
13070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
13170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
13270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->have_spawn_errno = FALSE;
13370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->have_child_status = FALSE;
13470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
13570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return sitter;
13670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
13770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
13870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/**
13970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Increment the reference count on the babysitter object.
14070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
14170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * @param sitter the babysitter
14270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * @returns the babysitter
14370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker */
14470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf HabackerDBusBabysitter *
14570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_ref (DBusBabysitter *sitter)
14670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
14770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
14870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_assert (sitter != NULL);
14970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_assert (sitter->refcount > 0);
15070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
15170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->refcount += 1;
15270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
15370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return sitter;
15470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
15570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
15670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/**
15770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Decrement the reference count on the babysitter object.
15870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
15970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * @param sitter the babysitter
16070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker */
16170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackervoid
16270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_unref (DBusBabysitter *sitter)
16370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
16470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  int i;
16570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
16670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
16770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_assert (sitter != NULL);
16870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_assert (sitter->refcount > 0);
16970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
17070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->refcount -= 1;
17170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
17270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->refcount == 0)
17370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
17470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->socket_to_babysitter != -1)
17570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
17670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          _dbus_close_socket (sitter->socket_to_babysitter, NULL);
17770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->socket_to_babysitter = -1;
17870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
17970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
18070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->socket_to_main != -1)
18170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
18270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          _dbus_close_socket (sitter->socket_to_main, NULL);
18370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->socket_to_main = -1;
18470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
18570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
18670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
18770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->argv != NULL)
18870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
18970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          for (i = 0; i < sitter->argc; i++)
19070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            if (sitter->argv[i] != NULL)
19170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              {
19270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                dbus_free (sitter->argv[i]);
19370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                sitter->argv[i] = NULL;
19470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              }
19570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          dbus_free (sitter->argv);
19670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->argv = NULL;
19770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
19870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
19970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->envp != NULL)
20070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
20170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          char **e = sitter->envp;
20270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
20370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          while (*e)
20470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            dbus_free (*e++);
20570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          dbus_free (sitter->envp);
20670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->envp = NULL;
20770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
20870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
20970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->child_handle != NULL)
21070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
21170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          CloseHandle (sitter->child_handle);
21270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->child_handle = NULL;
21370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
21470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
21570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->sitter_watch)
21670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
21770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          _dbus_watch_invalidate (sitter->sitter_watch);
21870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          _dbus_watch_unref (sitter->sitter_watch);
21970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->sitter_watch = NULL;
22070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
22170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
22270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->watches)
22370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        _dbus_watch_list_free (sitter->watches);
22470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
22570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->start_sync_event != NULL)
22670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
22770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          PING();
22870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          CloseHandle (sitter->start_sync_event);
22970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->end_sync_event = NULL;
23070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
23170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
23270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#ifdef DBUS_BUILD_TESTS
23370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (sitter->end_sync_event != NULL)
23470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
23570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          CloseHandle (sitter->end_sync_event);
23670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          sitter->end_sync_event = NULL;
23770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
23870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#endif
23970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
24070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_free (sitter->executable);
24170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
24270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_free (sitter);
24370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
24470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
24570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
24670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackervoid
24770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_kill_child (DBusBabysitter *sitter)
24870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
24970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
25070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->child_handle == NULL)
25170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return; /* child is already dead, or we're so hosed we'll never recover */
25270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
25370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
25470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  TerminateProcess (sitter->child_handle, 12345);
25570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
25670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
25770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/**
25870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Checks whether the child has exited, without blocking.
25970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
26070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * @param sitter the babysitter
26170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker */
26270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerdbus_bool_t
26370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_get_child_exited (DBusBabysitter *sitter)
26470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
26570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
26670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return (sitter->child_handle == NULL);
26770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
26870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
26970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/**
27070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * Sets the #DBusError with an explanation of why the spawned
27170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * child process exited (on a signal, or whatever). If
27270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * the child process has not exited, does nothing (error
27370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * will remain unset).
27470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker *
27570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * @param sitter the babysitter
27670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker * @param error an error to fill in
27770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker */
27870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackervoid
27970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_set_child_exit_error (DBusBabysitter *sitter,
28070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                       DBusError      *error)
28170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
28270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
28370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!_dbus_babysitter_get_child_exited (sitter))
28470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return;
28570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
28670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
28770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->have_spawn_errno)
28870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
28970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
29070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                      "Failed to execute program %s: %s",
29170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                      sitter->executable, _dbus_strerror (sitter->spawn_errno));
29270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
29370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  else if (sitter->have_child_status)
29470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
29570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
29670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
29770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                      "Process %s exited with status %d",
29870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                      sitter->executable, sitter->child_status);
29970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
30070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  else
30170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
30270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
30370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_set_error (error, DBUS_ERROR_FAILED,
30470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                      "Process %s exited, status unknown",
30570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                      sitter->executable);
30670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
30770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
30870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
30970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
31070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerdbus_bool_t
31170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_set_watch_functions (DBusBabysitter            *sitter,
31270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                      DBusAddWatchFunction       add_function,
31370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                      DBusRemoveWatchFunction    remove_function,
31470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                      DBusWatchToggledFunction   toggled_function,
31570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                      void                      *data,
31670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                      DBusFreeFunction           free_data_function)
31770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
31870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
31970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return _dbus_watch_list_set_functions (sitter->watches,
32070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         add_function,
32170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         remove_function,
32270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         toggled_function,
32370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         data,
32470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         free_data_function);
32570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
32670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
32770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic dbus_bool_t
32870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerhandle_watch (DBusWatch       *watch,
32970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              unsigned int     condition,
33070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              void            *data)
33170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
33270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusBabysitter *sitter = data;
33370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
33470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /* On Unix dbus-spawn uses a babysitter *process*, thus it has to
33570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * actually send the exit statuses, error codes and whatnot through
33670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * sockets and/or pipes. On Win32, the babysitter is jus a thread,
33770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * so it can set the status fields directly in the babysitter struct
33870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * just fine. The socket pipe is used just so we can watch it with
33970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * select(), as soon as anything is written to it we know that the
34070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * babysitter thread has recorded the status in the babysitter
34170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * struct.
34270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   */
34370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
34470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
34570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_close_socket (sitter->socket_to_babysitter, NULL);
34670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
34770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->socket_to_babysitter = -1;
34870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
34970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
35070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
35170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
35270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker/* protect_argv lifted from GLib, relicensed by author, Tor Lillqvist */
35370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic int
35470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerprotect_argv (char  **argv,
35570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              char ***new_argv)
35670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
35770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  int i;
35870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  int argc = 0;
35970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
36070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  while (argv[argc])
36170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    ++argc;
36270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  *new_argv = dbus_malloc ((argc + 1) * sizeof (char *));
36370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (*new_argv == NULL)
36470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return -1;
36570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
36670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  for (i = 0; i < argc; i++)
36770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    (*new_argv)[i] = NULL;
36870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
36970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /* Quote each argv element if necessary, so that it will get
37070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * reconstructed correctly in the C runtime startup code.  Note that
37170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * the unquoting algorithm in the C runtime is really weird, and
37270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * rather different than what Unix shells do. See stdargv.c in the C
37370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * runtime sources (in the Platform SDK, in src/crt).
37470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   *
37570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * Note that an new_argv[0] constructed by this function should
37670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * *not* be passed as the filename argument to a spawn* or exec*
37770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * family function. That argument should be the real file name
37870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * without any quoting.
37970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   */
38070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  for (i = 0; i < argc; i++)
38170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
38270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      char *p = argv[i];
38370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      char *q;
38470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      int len = 0;
38570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      int need_dblquotes = FALSE;
38670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      while (*p)
38770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
38870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          if (*p == ' ' || *p == '\t')
38970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            need_dblquotes = TRUE;
39070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          else if (*p == '"')
39170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            len++;
39270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          else if (*p == '\\')
39370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            {
39470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              char *pp = p;
39570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              while (*pp && *pp == '\\')
39670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                pp++;
39770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              if (*pp == '"')
39870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                len++;
39970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            }
40070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          len++;
40170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          p++;
40270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
40370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
40470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      q = (*new_argv)[i] = dbus_malloc (len + need_dblquotes*2 + 1);
40570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
40670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (q == NULL)
40770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        return -1;
40870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
40970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
41070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      p = argv[i];
41170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
41270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (need_dblquotes)
41370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        *q++ = '"';
41470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
41570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      while (*p)
41670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        {
41770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          if (*p == '"')
41870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            *q++ = '\\';
41970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          else if (*p == '\\')
42070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            {
42170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              char *pp = p;
42270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              while (*pp && *pp == '\\')
42370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                pp++;
42470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker              if (*pp == '"')
42570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                *q++ = '\\';
42670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker            }
42770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          *q++ = *p;
42870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker          p++;
42970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        }
43070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
43170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      if (need_dblquotes)
43270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        *q++ = '"';
43370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      *q++ = '\0';
43470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      /* printf ("argv[%d]:%s, need_dblquotes:%s len:%d => %s\n", i, argv[i], need_dblquotes?"TRUE":"FALSE", len, (*new_argv)[i]); */
43570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
43670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  (*new_argv)[argc] = NULL;
43770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
43870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return argc;
43970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
44070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
44170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic unsigned __stdcall
44270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerbabysitter (void *parameter)
44370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
44470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusBabysitter *sitter = (DBusBabysitter *) parameter;
44570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusSocket *sock;
44670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
44770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_babysitter_ref (sitter);
44870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
44970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->child_setup)
45070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
45170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
45270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      (*sitter->child_setup) (sitter->user_data);
45370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
45470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
45570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_verbose ("babysitter: spawning %s\n", sitter->executable);
45670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  fprintf (stderr, "babysitter: spawning %s\n", sitter->executable);
45770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
45870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
45970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->envp != NULL)
46070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    sitter->child_handle = (HANDLE) spawnve (P_NOWAIT, sitter->executable,
46170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                           (const char * const *) sitter->argv,
46270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                           (const char * const *) sitter->envp);
46370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  else
46470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    sitter->child_handle = (HANDLE) spawnv (P_NOWAIT, sitter->executable,
46570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                            (const char * const *) sitter->argv);
46670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
46770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
46870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->child_handle == (HANDLE) -1)
46970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
47070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      sitter->child_handle = NULL;
47170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      sitter->have_spawn_errno = TRUE;
47270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      sitter->spawn_errno = errno;
47370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
47470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
47570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
47670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  SetEvent (sitter->start_sync_event);
47770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
47870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->child_handle != NULL)
47970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
48070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      int ret;
48170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      DWORD status;
48270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
48370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
48470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      WaitForSingleObject (sitter->child_handle, INFINITE);
48570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
48670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
48770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      ret = GetExitCodeProcess (sitter->child_handle, &status);
48870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
48970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      sitter->child_status = status;
49070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      sitter->have_child_status = TRUE;
49170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
49270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      CloseHandle (sitter->child_handle);
49370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      sitter->child_handle = NULL;
49470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
49570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
49670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#ifdef DBUS_BUILD_TESTS
49770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  SetEvent (sitter->end_sync_event);
49870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#endif
49970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
50070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
50170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_handle_to_socket (sitter->socket_to_main, &sock);
50270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  send (sock->fd, " ", 1, 0);
50370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
50470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_babysitter_unref (sitter);
50570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
50670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return 0;
50770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
50870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
50970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerdbus_bool_t
51070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_spawn_async_with_babysitter (DBusBabysitter           **sitter_p,
51170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                   char                     **argv,
51270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                   char                     **envp,
51370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                   DBusSpawnChildSetupFunc    child_setup,
51470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                   void                      *user_data,
51570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                   DBusError                 *error)
51670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
51770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusBabysitter *sitter;
51870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  HANDLE sitter_thread;
51970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  int sitter_thread_id;
52070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
52170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
52270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
52370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  *sitter_p = NULL;
52470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
52570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
52670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter = _dbus_babysitter_new ();
52770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter == NULL)
52870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
52970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _DBUS_SET_OOM (error);
53070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
53170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
53270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
53370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->child_setup = child_setup;
53470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->user_data = user_data;
53570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
53670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->executable = _dbus_strdup (argv[0]);
53770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->executable == NULL)
53870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
53970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _DBUS_SET_OOM (error);
54070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      goto out0;
54170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
54270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
54370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
54470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!_dbus_full_duplex_pipe (&sitter->socket_to_babysitter,
54570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                               &sitter->socket_to_main,
54670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                               FALSE, error))
54770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    goto out0;
54870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
54970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter,
55070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                          DBUS_WATCH_READABLE,
55170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                          TRUE, handle_watch, sitter, NULL);
55270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
55370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->sitter_watch == NULL)
55470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
55570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _DBUS_SET_OOM (error);
55670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      goto out0;
55770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
55870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
55970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
56070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!_dbus_watch_list_add_watch (sitter->watches,  sitter->sitter_watch))
56170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
56270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _DBUS_SET_OOM (error);
56370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      goto out0;
56470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
56570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
56670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->argc = protect_argv (argv, &sitter->argv);
56770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->argc == -1)
56870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
56970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _DBUS_SET_OOM (error);
57070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      goto out0;
57170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
57270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter->envp = envp;
57370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
57470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
57570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter_thread = (HANDLE) _beginthreadex (NULL, 0, babysitter,
57670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                  sitter, 0, &sitter_thread_id);
57770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
57870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter_thread == 0)
57970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
58070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      PING();
58170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED,
58270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                            "Failed to create new thread");
58370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      goto out0;
58470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
58570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  CloseHandle (sitter_thread);
58670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
58770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
58870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  WaitForSingleObject (sitter->start_sync_event, INFINITE);
58970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
59070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
59170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter_p != NULL)
59270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    *sitter_p = sitter;
59370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  else
59470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    _dbus_babysitter_unref (sitter);
59570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
59670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
59770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
59870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  PING();
59970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
60070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
60170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerout0:
60270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  _dbus_babysitter_unref (sitter);
60370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
60470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return FALSE;
60570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
60670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
60770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#ifdef DBUS_BUILD_TESTS
60870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
60970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
61070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
61170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic void
61270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_babysitter_block_for_child_exit (DBusBabysitter *sitter)
61370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
61470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter->child_handle == NULL)
61570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return;
61670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
61770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  WaitForSingleObject (sitter->end_sync_event, INFINITE);
61870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
61970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
62070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic dbus_bool_t
62170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackercheck_spawn_nonexistent (void *data)
62270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
62370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  char *argv[4] = { NULL, NULL, NULL, NULL };
62470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusBabysitter *sitter;
62570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusError error;
62670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
62770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter = NULL;
62870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
62970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  dbus_error_init (&error);
63070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
63170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /*** Test launching nonexistent binary */
63270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
63370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  argv[0] = "/this/does/not/exist/32542sdgafgafdg";
63470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
63570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         NULL, NULL,
63670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         &error))
63770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
63870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_block_for_child_exit (sitter);
63970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_set_child_exit_error (sitter, &error);
64070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
64170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
64270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter)
64370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    _dbus_babysitter_unref (sitter);
64470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
64570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!dbus_error_is_set (&error))
64670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
64770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Did not get an error launching nonexistent executable\n");
64870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
64970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
65070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
65170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
65270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
65370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
65470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n",
65570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                  error.name, error.message);
65670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_error_free (&error);
65770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
65870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
65970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
66070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  dbus_error_free (&error);
66170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
66270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
66370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
66470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
66570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic dbus_bool_t
66670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackercheck_spawn_segfault (void *data)
66770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
66870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  char *argv[4] = { NULL, NULL, NULL, NULL };
66970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusBabysitter *sitter;
67070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusError error;
67170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
67270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter = NULL;
67370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
67470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  dbus_error_init (&error);
67570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
67670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /*** Test launching segfault binary */
67770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
67870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  argv[0] = TEST_SEGFAULT_BINARY;
67970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
68070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         NULL, NULL,
68170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         &error))
68270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
68370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_block_for_child_exit (sitter);
68470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_set_child_exit_error (sitter, &error);
68570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
68670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
68770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter)
68870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    _dbus_babysitter_unref (sitter);
68970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
69070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!dbus_error_is_set (&error))
69170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
69270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Did not get an error launching segfaulting binary\n");
69370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
69470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
69570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
69670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
69770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
69870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
69970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n",
70070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                  error.name, error.message);
70170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_error_free (&error);
70270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
70370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
70470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
70570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  dbus_error_free (&error);
70670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
70770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
70870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
70970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
71070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic dbus_bool_t
71170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackercheck_spawn_exit (void *data)
71270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
71370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  char *argv[4] = { NULL, NULL, NULL, NULL };
71470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusBabysitter *sitter;
71570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusError error;
71670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
71770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter = NULL;
71870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
71970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  dbus_error_init (&error);
72070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
72170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /*** Test launching exit failure binary */
72270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
72370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  argv[0] = TEST_EXIT_BINARY;
72470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
72570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         NULL, NULL,
72670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         &error))
72770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
72870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_block_for_child_exit (sitter);
72970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_set_child_exit_error (sitter, &error);
73070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
73170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
73270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter)
73370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    _dbus_babysitter_unref (sitter);
73470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
73570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!dbus_error_is_set (&error))
73670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
73770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Did not get an error launching binary that exited with failure code\n");
73870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
73970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
74070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
74170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
74270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
74370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
74470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n",
74570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                  error.name, error.message);
74670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_error_free (&error);
74770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
74870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
74970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
75070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  dbus_error_free (&error);
75170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
75270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
75370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
75470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
75570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerstatic dbus_bool_t
75670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackercheck_spawn_and_kill (void *data)
75770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
75870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  char *argv[4] = { NULL, NULL, NULL, NULL };
75970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusBabysitter *sitter;
76070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  DBusError error;
76170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
76270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  sitter = NULL;
76370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
76470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  dbus_error_init (&error);
76570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
76670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /*** Test launching sleeping binary then killing it */
76770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
76870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  argv[0] = TEST_SLEEP_FOREVER_BINARY;
76970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL,
77070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         NULL, NULL,
77170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                         &error))
77270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
77370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_kill_child (sitter);
77470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
77570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_block_for_child_exit (sitter);
77670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
77770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_babysitter_set_child_exit_error (sitter, &error);
77870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
77970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
78070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (sitter)
78170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    _dbus_babysitter_unref (sitter);
78270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
78370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!dbus_error_is_set (&error))
78470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
78570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Did not get an error after killing spawned binary\n");
78670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
78770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
78870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
78970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
79070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker        dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
79170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    {
79270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      _dbus_warn ("Not expecting error when killing executable: %s: %s\n",
79370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                  error.name, error.message);
79470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      dbus_error_free (&error);
79570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
79670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    }
79770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
79870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  dbus_error_free (&error);
79970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
80070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
80170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
80270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
80370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habackerdbus_bool_t
80470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker_dbus_spawn_test (const char *test_data_dir)
80570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker{
80670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!_dbus_test_oom_handling ("spawn_nonexistent",
80770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                check_spawn_nonexistent,
80870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                NULL))
80970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return FALSE;
81070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
81170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  /* Don't run the obnoxious segfault test by default,
81270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   * it's a pain to have to click all those error boxes.
81370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker   */
81470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (getenv ("DO_SEGFAULT_TEST"))
81570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    if (!_dbus_test_oom_handling ("spawn_segfault",
81670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                  check_spawn_segfault,
81770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                  NULL))
81870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker      return FALSE;
81970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
82070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!_dbus_test_oom_handling ("spawn_exit",
82170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                check_spawn_exit,
82270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                NULL))
82370bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return FALSE;
82470bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
82570bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  if (!_dbus_test_oom_handling ("spawn_and_kill",
82670bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                check_spawn_and_kill,
82770bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker                                NULL))
82870bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker    return FALSE;
82970bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker
83070bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker  return TRUE;
83170bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker}
83270bfc74e54ac8a9a93885710cd8350d1a58b3406Ralf Habacker#endif
833