5#if !defined(SPAWN_DEBUG) || defined(_MSC_VER) 
    8#define PING() fprintf (stderr, "%s:%s:%d\n", __FILE__, _DBUS_FUNCTION_NAME, __LINE__); fflush (stderr) 
   39#include "dbus-spawn.h" 
   40#include "dbus-sysdeps.h" 
   41#include "dbus-sysdeps-win.h" 
   42#include "dbus-internals.h" 
   44#include "dbus-protocol.h" 
   46#define WIN32_LEAN_AND_MEAN 
   71    DBusSocket socket_to_main;
 
   75    DBusBabysitterFinishedFunc finished_cb;
 
   90#ifdef DBUS_ENABLE_VERBOSE_MODE 
   91  static int enabled = -1;
 
   93  _dbus_trace_ref (
"DBusBabysitter", sitter, old_refcount, new_refcount, why,
 
   94      "DBUS_BABYSITTER_TRACE", &enabled);
 
   99_dbus_babysitter_new (
void)
 
  110  _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, _DBUS_FUNCTION_NAME);
 
  112  sitter->child_handle = 
NULL;
 
  123  sitter->have_spawn_errno = 
FALSE;
 
  144  _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount+1, _DBUS_FUNCTION_NAME);
 
 
  152  _dbus_verbose (
"Closing babysitter\n");
 
  185  _dbus_babysitter_trace_ref (sitter, old_refcount, old_refcount-1, _DBUS_FUNCTION_NAME);
 
  187  if (old_refcount == 1)
 
  189      close_socket_to_babysitter (sitter);
 
  191      if (sitter->socket_to_main.sock != INVALID_SOCKET)
 
  194          sitter->socket_to_main.sock = INVALID_SOCKET;
 
  197      if (sitter->child_handle != 
NULL)
 
  199          CloseHandle (sitter->child_handle);
 
  200          sitter->child_handle = 
NULL;
 
  213      if (sitter->thread_handle)
 
  215          CloseHandle (sitter->thread_handle);
 
  216          sitter->thread_handle = 
NULL;
 
 
  229  if (sitter->child_handle == 
NULL)
 
  233  TerminateProcess (sitter->child_handle, 12345);
 
 
  245  return (sitter->child_handle == 
NULL);
 
 
  268      sitter->child_status == STILL_ACTIVE)
 
  271  *status = sitter->child_status;
 
 
  293  if (sitter->have_spawn_errno)
 
  295      char *emsg = _dbus_win_error_string (sitter->spawn_errno);
 
  297                      "Failed to execute program %s: %s",
 
  299      _dbus_win_free_error_string (emsg);
 
  305                      "Process %s exited with status %d",
 
  306                      sitter->
log_name, sitter->child_status);
 
  312                      "Process %s exited, status unknown",
 
 
  337              unsigned int     condition,
 
  353  close_socket_to_babysitter (sitter);
 
  357      sitter->finished_cb != 
NULL)
 
  359      sitter->finished_cb (sitter, sitter->finished_data);
 
  360      sitter->finished_cb = 
NULL;
 
  368protect_argv (
char  * 
const *argv,
 
  381  for (i = 0; i < argc; i++)
 
  395  for (i = 0; i < argc; i++)
 
  397      const char *p = argv[i];
 
  400      int need_dblquotes = 
FALSE;
 
  403          if (*p == 
' ' || *p == 
'\t')
 
  404            need_dblquotes = 
TRUE;
 
  410              while (*pp && *pp == 
'\\')
 
  419      q = args[i] = 
dbus_malloc (len + need_dblquotes*2 + 1);
 
  439              while (*pp && *pp == 
'\\')
 
  460build_commandline (
char **argv, 
DBusString *result)
 
  466build_env_block (
char** envp, 
DBusString *result)
 
  492_dbus_spawn_program (
const char *name,
 
  498  PROCESS_INFORMATION pi = { 
NULL, 0, 0, 0 };
 
  500  DBusString arg_string = _DBUS_STRING_INIT_INVALID;
 
  501  DBusString env_block = _DBUS_STRING_INIT_INVALID;
 
  507      _DBUS_SET_OOM (error);
 
  514      if (!build_commandline (argv + 1, &arg_string))
 
  515        _DBUS_SET_OOM (error);
 
  519  if (!build_commandline (argv, &arg_string))
 
  521      _DBUS_SET_OOM (error);
 
  525  if (_dbus_string_get_length (&arg_string) == 0)
 
  533      if (!build_env_block (envp, &env_block))
 
  535          _DBUS_SET_OOM (error);
 
  539      env = _dbus_string_get_data (&env_block);
 
  542  memset (&si, 0, 
sizeof (si));
 
  545#ifdef DBUS_ENABLE_VERBOSE_MODE 
  551      _DBUS_SET_OOM (error);
 
  558        _DBUS_SET_OOM (error);
 
  562    _dbus_verbose (
"spawning '%s'' with args: '%s' env: '%s'\n", name,
 
  563                   _dbus_string_get_const_data (&arg_string),
 
  564                   _dbus_string_get_const_data (&temp));
 
  570  result = CreateProcessA (name, _dbus_string_get_const_data (&arg_string), 
NULL, 
NULL, 
FALSE, 0,
 
  572  result = CreateProcessA (
NULL,  
 
  573                           _dbus_string_get_data (&arg_string),
 
  579                           env, 
NULL, &si, &pi);
 
  582      _dbus_win_set_error_from_last_error (error, 
"Unable to start '%s' with arguments '%s'",
 
  583                                           name, _dbus_string_get_const_data (&arg_string));
 
  588  _DBUS_ASSERT_ERROR_XOR_BOOL (error, result);
 
  595      CloseHandle (pi.hThread);
 
  603static DWORD __stdcall
 
  604babysitter (
void *parameter)
 
  610  if (sitter->child_handle != 
NULL)
 
  616      WaitForSingleObject (sitter->child_handle, INFINITE);
 
  619      ret = GetExitCodeProcess (sitter->child_handle, &status);
 
  622          sitter->child_status = status;
 
  626      CloseHandle (sitter->child_handle);
 
  627      sitter->child_handle = 
NULL;
 
  631  send (sitter->socket_to_main.sock, 
" ", 1, 0);
 
  640                                   const char                *log_name,
 
  643                                   DBusSpawnFlags             flags _DBUS_GNUC_UNUSED,
 
  644                                   DBusSpawnChildSetupFunc    child_setup _DBUS_GNUC_UNUSED,
 
  645                                   void                      *user_data _DBUS_GNUC_UNUSED,
 
  649  DWORD sitter_thread_id;
 
  652  char **my_argv = 
NULL;
 
  655  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
  658  if (sitter_p != 
NULL)
 
  662  sitter = _dbus_babysitter_new ();
 
  665      _DBUS_SET_OOM (error);
 
  672      _DBUS_SET_OOM (error);
 
  681      _DBUS_SET_OOM (error);
 
  687                         &sitter->socket_to_main,
 
  697      _DBUS_SET_OOM (error);
 
  710      _DBUS_SET_OOM (error);
 
  714  argc = protect_argv (argv, &my_argv);
 
  717      _DBUS_SET_OOM (error);
 
  721  _dbus_verbose (
"babysitter: spawn child '%s'\n", my_argv[0]);
 
  724  handle = _dbus_spawn_program (sitter->
log_name, my_argv, (
char **) envp, 
FALSE, &local_error);
 
  736          sitter->child_handle = 
NULL;
 
  737          sitter->have_spawn_errno = 
TRUE;
 
  738          sitter->spawn_errno = ERROR_NOT_ENOUGH_MEMORY;
 
  743          sitter->child_handle = 
NULL;
 
  744          sitter->have_spawn_errno = 
TRUE;
 
  745          sitter->spawn_errno = GetLastError();
 
  747                          "Failed to spawn child: %s", local_error.
message);
 
  755  sitter->child_handle = handle;
 
  758  sitter->thread_handle = (HANDLE) CreateThread (
NULL, 0, babysitter,
 
  761  if (sitter->thread_handle == 
NULL)
 
  765                            "Failed to create new thread");
 
  770  if (sitter_p != 
NULL)
 
  775  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
  788                                       DBusBabysitterFinishedFunc  finished,
 
  791  sitter->finished_cb = finished;
 
  792  sitter->finished_data = user_data;
 
  795#define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL) 
  803  WaitForSingleObject (sitter->thread_handle, INFINITE);
 
void(* DBusWatchToggledFunction)(DBusWatch *watch, void *data)
Called when dbus_watch_get_enabled() may return a different value than it did before.
dbus_bool_t(* DBusAddWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus needs a new watch to be monitored by the main loop.
void(* DBusRemoveWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus no longer needs a watch to be monitored by the main loop.
@ DBUS_WATCH_READABLE
As in POLLIN.
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
void dbus_move_error(DBusError *src, DBusError *dest)
Moves an error src into dest, freeing src and overwriting dest.
void dbus_set_error_const(DBusError *error, const char *name, const char *message)
Assigns an error name and message to a DBusError.
dbus_bool_t dbus_error_has_name(const DBusError *error, const char *name)
Checks whether the error is set and has the given name.
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
dbus_bool_t _dbus_babysitter_get_child_exit_status(DBusBabysitter *sitter, int *status)
Gets the exit status of the child.
void _dbus_babysitter_unref(DBusBabysitter *sitter)
Decrement the reference count on the babysitter object.
dbus_bool_t _dbus_babysitter_get_child_exited(DBusBabysitter *sitter)
Checks whether the child has exited, without blocking.
dbus_bool_t _dbus_babysitter_set_watch_functions(DBusBabysitter *sitter, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets watch functions to notify us when the babysitter object needs to read/write file descriptors.
char * _dbus_strdup(const char *str)
Duplicates a string.
void _dbus_babysitter_set_child_exit_error(DBusBabysitter *sitter, DBusError *error)
Sets the DBusError with an explanation of why the spawned child process exited (on a signal,...
void _dbus_babysitter_kill_child(DBusBabysitter *sitter)
Blocks until the babysitter process gives us the PID of the spawned grandchild, then kills the spawne...
DBusBabysitter * _dbus_babysitter_ref(DBusBabysitter *sitter)
Increment the reference count on the babysitter object.
dbus_bool_t _dbus_spawn_async_with_babysitter(DBusBabysitter **sitter_p, const char *log_name, char *const *argv, char *const *env, DBusSpawnFlags flags, DBusSpawnChildSetupFunc child_setup, void *user_data, DBusError *error)
Spawns a new process.
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
#define DBUS_ERROR_SPAWN_CHILD_EXITED
While starting a new process, the child exited with a status code.
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
#define DBUS_ERROR_SPAWN_FORK_FAILED
While starting a new process, the fork() call failed.
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
dbus_bool_t _dbus_string_append_strings(DBusString *str, char **strings, char separator)
Append vector with strings connected by separator.
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as _DBUS_STRING_IN...
dbus_bool_t _dbus_string_append_byte(DBusString *str, unsigned char byte)
Appends a single byte to the string, returning FALSE if not enough memory.
struct DBusAtomic DBusAtomic
Opaque type representing an atomically-modifiable integer that can be used from multiple threads.
dbus_bool_t _dbus_socketpair(DBusSocket *fd1, DBusSocket *fd2, dbus_bool_t blocking, DBusError *error)
Creates pair of connect sockets (as in socketpair()).
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
dbus_bool_t _dbus_close_socket(DBusSocket *fd, DBusError *error)
Closes a socket and invalidates it.
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
int dbus_int32_t
A 32-bit signed integer on all platforms.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
dbus_bool_t _dbus_watch_list_add_watch(DBusWatchList *watch_list, DBusWatch *watch)
Adds a new watch to the watch list, invoking the application DBusAddWatchFunction if appropriate.
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
struct DBusWatchList DBusWatchList
Opaque data type representing a list of watches and a set of DBusAddWatchFunction/DBusRemoveWatchFunc...
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
dbus_bool_t _dbus_watch_list_set_functions(DBusWatchList *watch_list, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets the watch functions.
DBusWatch * _dbus_watch_new(DBusPollable fd, unsigned int flags, dbus_bool_t enabled, DBusWatchHandler handler, void *data, DBusFreeFunction free_data_function)
Creates a new DBusWatch.
void _dbus_watch_unref(DBusWatch *watch)
Decrements the reference count of a DBusWatch object and finalizes the object if the count reaches ze...
void _dbus_watch_list_remove_watch(DBusWatchList *watch_list, DBusWatch *watch)
Removes a watch from the watch list, invoking the application's DBusRemoveWatchFunction if appropriat...
void _dbus_watch_invalidate(DBusWatch *watch)
Clears the file descriptor from a now-invalid watch object so that no one tries to use it.
Babysitter implementation details.
DBusWatch * sitter_watch
Sitter pipe watch.
DBusSocket socket_to_babysitter
Connection to the babysitter process.
unsigned int have_child_status
True if child status has been reaped.
char * log_name
the name under which to log messages about this process being spawned
int refcount
Reference count.
DBusWatchList * watches
Watches.
Object representing an exception.
const char * message
public error message field
Implementation of DBusWatch.