Beispiel #1
0
void WorkQueue::dispatchOnTermination(WebKit::PlatformProcessIdentifier process, const Function<void()>& function)
{
    GRefPtr<GSource> dispatchSource = adoptGRef(g_child_watch_source_new(process));
    ASSERT(dispatchSource);

    dispatchOnSource(dispatchSource.get(), function, reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWorkOnTermination));
}
Beispiel #2
0
static gchar *
gnuindent (GrindBackendGNUIndent *self,
           GeanyDocument         *doc,
           const gchar           *input,
           GError               **error)
{
  GPid    pid;
  int     input_fd;
  int     output_fd;
  int     error_fd;
  gchar  *output = NULL;
  gchar **argv;
  
  argv = build_args (self, doc);
  if (g_spawn_async_with_pipes (NULL, argv, NULL,
                                G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
                                NULL, NULL, &pid, &input_fd, &output_fd,
                                &error_fd, error)) {
    GSource      *source;
    GMainContext *ctx = g_main_context_new ();
    BlockData     data;
    
    data.error = NULL;
    data.loop = g_main_loop_new (ctx, FALSE);
    data.output_str = g_string_new (NULL);
    data.error_str = g_string_new (NULL);
    
    source = g_child_watch_source_new (pid);
    g_source_set_callback (source, (GSourceFunc)child_watch_handler,
                           &data, NULL);
    g_source_attach (source, ctx);
    g_source_unref (source);
    
    /* output */
    add_watch_fd (output_fd,
                  G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL, ctx,
                  (GIOFunc)output_ready_handler, &data);
    /* error */
    add_watch_fd (error_fd,
                  G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL, ctx,
                  (GIOFunc)error_ready_handler, &data);
    
    if (write_input (input_fd, input, &data.error)) {
      g_main_loop_run (data.loop);
    }
      
    if (! data.error) {
      output = g_string_free (data.output_str, FALSE);
    } else {
      g_string_free (data.output_str, TRUE);
      g_propagate_error (error, data.error);
    }
    g_string_free (data.error_str, TRUE);
    g_main_loop_unref (data.loop);
    g_main_context_unref (ctx);
  }
  g_strfreev (argv);
  
  return output;
}
void WorkQueue::scheduleWorkOnTermination(WebKit::PlatformProcessIdentifier process, PassOwnPtr<WorkItem> item)
{
    GRefPtr<GSource> dispatchSource = adoptGRef(g_child_watch_source_new(process));
    ASSERT(dispatchSource);

    scheduleWorkOnSource(dispatchSource.get(), item, reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWorkOnTermination));
}
Beispiel #4
0
/**
 * g_child_watch_add will bind the source to the "main" main context,
 * g_main_context_get_default(), which is not what we want
 */
static int g_child_watch_add_tothread(GPid pid,
                                      GChildWatchFunc function, gpointer data)
{
    GSource *source;
    guint id;

    g_return_val_if_fail(function != NULL, 0);
    g_return_val_if_fail(pid > 0, 0);

    source = g_child_watch_source_new(pid);

    g_source_set_callback(source, (GSourceFunc) function, data, NULL);
    id = g_source_attach(source, g_main_context_get_thread_default());
    g_source_unref(source);

    return id;
}
Beispiel #5
0
static gboolean
PowerOpsRunScript(PowerOpState *state,
                  gchar *script)
{
   gchar *argv[2];
   GSource *watch;
   GError *err = NULL;

   argv[0] = g_locale_from_utf8(script, -1, NULL, NULL, &err);
   if (err != NULL) {
      g_debug("Conversion error: %s\n", err->message);
      g_clear_error(&err);
      /*
       * If we could not convert to current locate let's hope that
       * what we have is a useable script name and use it directly.
       */
      argv[0] = g_strdup(script);
   }
   argv[1] = NULL;

   g_message("Executing script: '%s'\n", script);
   if (!g_spawn_async(NULL,
                      argv,
                      NULL,
                      G_SPAWN_DO_NOT_REAP_CHILD |
                      G_SPAWN_STDOUT_TO_DEV_NULL |
                      G_SPAWN_STDERR_TO_DEV_NULL,
                      NULL,
                      NULL,
                      &state->pid,
                      &err)) {
         g_warning("Error starting script: %s\n", err->message);
         g_clear_error(&err);
         g_free(argv[0]);
         return FALSE;
   }

   /* Setup a watch for when the child is done. */
   watch = g_child_watch_source_new(state->pid);
   VMTOOLSAPP_ATTACH_SOURCE(state->ctx, watch, PowerOpsScriptCallback, state, NULL);
   g_source_unref(watch);
   g_free(argv[0]);
   return TRUE;
}
Beispiel #6
0
void SpiceController::WaitForPid(GPid pid)
{
    GMainContext *context;
    GSource *source;

    context = g_main_context_new();

    m_child_watch_mainloop = g_main_loop_new(context, FALSE);
    source = g_child_watch_source_new(pid);
    g_source_set_callback(source, (GSourceFunc)ChildExited, this, NULL);
    g_source_attach(source, context);

    g_main_loop_run(m_child_watch_mainloop);

    g_main_loop_unref(m_child_watch_mainloop);
    g_main_context_unref(context);

    g_spawn_close_pid(pid);
    if (pid == m_pid_controller)
        m_pid_controller = 0;
}
static guint
watch_child_full (GCutEventLoop *loop,
                  gint             priority,
                  GPid             pid,
                  GChildWatchFunc  function,
                  gpointer         data,
                  GDestroyNotify   notify)
{
    GCutGLibEventLoopPrivate *priv;
    guint tag;
    GSource *source;

    priv = GCUT_GLIB_EVENT_LOOP_GET_PRIVATE(loop);
    source = g_child_watch_source_new(pid);
    if (priority != G_PRIORITY_DEFAULT)
        g_source_set_priority(source, priority);
    g_source_set_callback(source, (GSourceFunc)function, data, notify);
    tag = g_source_attach(source, g_main_loop_get_context(priv->loop));
    g_source_unref(source);

    return tag;
}
static gpointer
test_thread (gpointer data)
{
  GMainLoop *new_main_loop;
  GSource *source;
  GPid pid;
  gint ttl = GPOINTER_TO_INT (data);

  new_main_loop = g_main_loop_new (NULL, FALSE);

  pid = get_a_child (ttl);
  source = g_child_watch_source_new (pid);
  g_source_set_callback (source, (GSourceFunc) child_watch_callback, data, NULL);
  g_source_attach (source, g_main_loop_get_context (new_main_loop));
  g_source_unref (source);

#ifdef VERBOSE
  g_print ("whee! created pid: " GPID_FORMAT " (ttl %d)\n", pid, ttl);
#endif

  g_main_loop_run (new_main_loop);

  return NULL;
}
Beispiel #9
0
static verto_mod_ev *
glib_ctx_add(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags)
{
    verto_mod_ev *evpriv = NULL;
    verto_ev_type type = verto_get_type(ev);

    *flags |= verto_get_flags(ev) & VERTO_EV_FLAG_PERSIST;
    *flags |= verto_get_flags(ev) & VERTO_EV_FLAG_IO_CLOSE_FD;

    switch (type) {
        case VERTO_EV_TYPE_IO:
            evpriv = g_source_new(&funcs, sizeof(GIOSource));
            if (evpriv) {
                ((GIOSource*) evpriv)->fd.fd = verto_get_fd(ev);
                ((GIOSource*) evpriv)->autoclose =
                        *flags & VERTO_EV_FLAG_IO_CLOSE_FD;
                g_source_add_poll(evpriv, &((GIOSource*) evpriv)->fd);
            }
            break;
        case VERTO_EV_TYPE_TIMEOUT:
            evpriv = g_timeout_source_new(verto_get_interval(ev));
            break;
        case VERTO_EV_TYPE_IDLE:
            evpriv = g_idle_source_new();
            break;
        case VERTO_EV_TYPE_CHILD:
            evpriv = g_child_watch_source_new(verto_get_proc(ev));
            break;
        case VERTO_EV_TYPE_SIGNAL:
/* While glib has signal support in >=2.29, it does not support many
   common signals (like USR*). Therefore, signal support is disabled
   until they support them (should be soonish) */
#if GLIB_MAJOR_VERSION >= 999
#if GLIB_MINOR_VERSION >= 29
#ifdef G_OS_UNIX /* Not supported on Windows */
            evpriv = g_unix_signal_source_new(verto_get_signal(ev));
            break;
#endif
#endif /* GLIB_MINOR_VERSION >= 29 */
#endif /* GLIB_MAJOR_VERSION >= 2 */
        default:
            return NULL; /* Not supported */
    }

    if (!evpriv)
        goto error;

    if (type == VERTO_EV_TYPE_IO)
        g_source_set_callback(evpriv, (GSourceFunc) glib_callback_io,
                              (void *) ev, NULL);
    else if (type == VERTO_EV_TYPE_CHILD)
        g_source_set_callback(evpriv, (GSourceFunc) glib_callback_child,
                              (void *) ev, NULL);
    else
        g_source_set_callback(evpriv, glib_callback, (void *) ev, NULL);

    glib_ctx_set_flags(ctx, ev, evpriv);

    g_source_set_can_recurse(evpriv, FALSE);
    if (g_source_attach(evpriv, ctx->context) == 0)
        goto error;

    return evpriv;

    error:
        if (evpriv) {
            g_source_destroy(evpriv);
            g_source_unref(evpriv);
        }
        return NULL;
}
static gboolean
nm_openssh_start (NMVPNPlugin *plugin, NMSettingVPN *s_vpn, GError **error)
{
	NMOpensshPluginPrivate *priv = NM_OPENSSH_PLUGIN_GET_PRIVATE(plugin);
	sshtun_handle_t handle;
	const char *tun_mode;
	char *tun_owner = NULL, *host = NULL, *user = NULL,
		*public_key = NULL, *private_key = NULL, *config_script = NULL;
	const char *val;
	int ret;
	gboolean retval = TRUE;
	GIOChannel *event_channel;
	GSource *child_watch, *event_watch;

	val = nm_setting_vpn_get_user_name (s_vpn);
	if (!val) {
		g_set_error (error,
					 NM_VPN_PLUGIN_ERROR,
					 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
					 "%s",
					 "Can't get username.");
		retval = FALSE;
		goto out;
	}
	tun_owner = g_strdup (val);

	val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_TUN_USE_TAP);
	tun_mode = val && !strcmp (val, "yes") ? "ethernet" : "pointopoint";

	val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_USER);
	user = val ? g_strdup (val) : g_strdup (tun_owner);

	val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_HOST);
	if (!val) {
		g_set_error (error,
					 NM_VPN_PLUGIN_ERROR,
					 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
					 "%s",
					 "Host is missing.");
		retval = FALSE;
		goto out;
	}
	host = g_strdup (val);

	val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_PUBLIC_KEY);
	if (!val) {
		g_set_error (error,
					 NM_VPN_PLUGIN_ERROR,
					 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
					 "%s",
					 "SSH public key is missing.");
		retval = FALSE;
		goto out;
	}
	public_key = g_strdup (val);

	val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_PRIVATE_KEY);
	if (!val) {
		g_set_error (error,
					 NM_VPN_PLUGIN_ERROR,
					 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
					 "%s",
					 "SSH private key is missing.");
		retval = FALSE;
		goto out;
	}
	private_key = g_strdup (val);

	val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_CONFIG_SCRIPT);
	if (!val) {
		g_set_error (error,
					 NM_VPN_PLUGIN_ERROR,
					 NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
					 "%s",
					 "IP config script is missing.");
		retval = FALSE;
		goto out;
	}
	config_script = g_strdup (val);

	ret = sshtun_new (&handle);
	if (ret < 0) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_GENERAL,
		             "%s",
		             "Could not allocate memory for an sshtun process.");
		retval = FALSE;
		goto out;
	}

	ret = sshtun_set_params (handle,
							 SSHTUN_PARAM_TUN_MODE, tun_mode,
							 SSHTUN_PARAM_TUN_OWNER, tun_owner,
							 SSHTUN_PARAM_USER, user,
							 SSHTUN_PARAM_HOST, host,
							 SSHTUN_PARAM_SERVICE, "ssh",
							 SSHTUN_PARAM_PUBLIC_KEY, public_key,
							 SSHTUN_PARAM_PRIVATE_KEY, private_key,
							 SSHTUN_PARAM_CONFIG_SCRIPT, config_script,
							 0);
	if (ret < 0) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
		             "%s",
		             "Could not set parameters for an sshtun process.");
		retval = FALSE;
		goto out;
	}

	ret = sshtun_start (handle);
	if (ret < 0) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
		             "%s",
		             "Could not start an sshtun process.");
		retval = FALSE;
		goto out;
	}

	priv->handle = handle;

	val = nm_setting_vpn_get_secret (s_vpn, NM_OPENSSH_KEY_PASSWORD);
	priv->password = val ? g_strdup (val) : NULL;

	/* Watch the status change of the sshtun child process. */
	child_watch = g_child_watch_source_new (sshtun_pid (priv->handle));
	g_source_set_callback (child_watch,
						   (GSourceFunc) child_watch_cb, plugin,
						   NULL);
	g_source_attach (child_watch, NULL);
	g_source_unref (child_watch);

	/* Watch the normal event from the sshtun child process. */
	event_channel =	g_io_channel_unix_new (sshtun_event_fd (priv->handle));
	event_watch = g_io_create_watch (event_channel, G_IO_IN);
	g_source_set_callback (event_watch,
						   (GSourceFunc) event_watch_cb, plugin,
						   NULL);
	g_source_attach (event_watch, NULL);
	g_source_unref (event_watch);
	g_io_channel_unref (event_channel);

 out:
	g_free (tun_owner);
	g_free (host);
	g_free (user);
	g_free (public_key);
	g_free (private_key);
	g_free (config_script);

	return retval;
}
Beispiel #11
0
/* called when we're done running the command line */
static void
udisks_spawned_job_release_resources (UlSpawnedJob *self)
{
  /* Nuke the child, if necessary */
  if (self->child_watch_source != NULL)
    {
      g_source_destroy (self->child_watch_source);
      self->child_watch_source = NULL;
    }

  if (self->child_pid != 0)
    {
      GSource *source;

      g_debug ("ugh, need to kill %d", (gint) self->child_pid);
      kill (self->child_pid, SIGTERM);

      /* OK, we need to reap for the child ourselves - we don't want
       * to use waitpid() because that might block the calling
       * thread (the child might handle SIGTERM and use several
       * seconds for cleanup/rollback).
       *
       * So we use GChildWatch instead.
       *
       * Note that we might be called from the finalizer so avoid
       * taking references to ourselves. We do need to pass the
       * GSource so we can nuke it once handled.
       */
      source = g_child_watch_source_new (self->child_pid);
      g_source_set_callback (source,
                             (GSourceFunc) child_watch_from_release_cb,
                             source,
                             (GDestroyNotify) g_source_destroy);
      g_source_attach (source, self->main_context);
      g_source_unref (source);

      self->child_pid = 0;
    }

  if (self->child_stdout != NULL)
    {
      g_string_free (self->child_stdout, TRUE);
      self->child_stdout = NULL;
    }

  if (self->child_stderr != NULL)
    {
      g_string_free (self->child_stderr, TRUE);
      self->child_stderr = NULL;
    }

  if (self->child_stdin_channel != NULL)
    {
      g_io_channel_unref (self->child_stdin_channel);
      self->child_stdin_channel = NULL;
    }
  if (self->child_stdout_channel != NULL)
    {
      g_io_channel_unref (self->child_stdout_channel);
      self->child_stdout_channel = NULL;
    }
  if (self->child_stderr_channel != NULL)
    {
      g_io_channel_unref (self->child_stderr_channel);
      self->child_stderr_channel = NULL;
    }

  if (self->child_stdin_source != NULL)
    {
      g_source_destroy (self->child_stdin_source);
      self->child_stdin_source = NULL;
    }
  if (self->child_stdout_source != NULL)
    {
      g_source_destroy (self->child_stdout_source);
      self->child_stdout_source = NULL;
    }
  if (self->child_stderr_source != NULL)
    {
      g_source_destroy (self->child_stderr_source);
      self->child_stderr_source = NULL;
    }

  if (self->child_stdin_fd != -1)
    {
      g_warn_if_fail (close (self->child_stdin_fd) == 0);
      self->child_stdin_fd = -1;
    }
  if (self->child_stdout_fd != -1)
    {
      g_warn_if_fail (close (self->child_stdout_fd) == 0);
      self->child_stdout_fd = -1;
    }
  if (self->child_stderr_fd != -1)
    {
      g_warn_if_fail (close (self->child_stderr_fd) == 0);
      self->child_stderr_fd = -1;
    }

  if (self->cancellable_handler_id > 0)
    {
      g_cancellable_disconnect (ul_job_get_cancellable (UL_JOB (self)),
                                self->cancellable_handler_id);
      self->cancellable_handler_id = 0;
    }
}
Beispiel #12
0
void
gvfs_udisks2_utils_spawn (guint                timeout_seconds,
                          GCancellable        *cancellable,
                          GAsyncReadyCallback  callback,
                          gpointer             user_data,
                          const gchar         *command_line_format,
                          ...)
{
  va_list var_args;
  SpawnData *data;
  GError *error;
  gint child_argc;
  gchar **child_argv = NULL;

  data = g_slice_new0 (SpawnData);
  data->simple = g_simple_async_result_new (NULL,
                                            callback,
                                            user_data,
                                            gvfs_udisks2_utils_spawn);
  data->main_context = g_main_context_get_thread_default ();
  if (data->main_context != NULL)
    g_main_context_ref (data->main_context);

  data->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;

  va_start (var_args, command_line_format);
  data->command_line = g_strdup_vprintf (command_line_format, var_args);
  va_end (var_args);

  data->child_stdout = g_string_new (NULL);
  data->child_stderr = g_string_new (NULL);
  data->child_stdout_fd = -1;
  data->child_stderr_fd = -1;

  /* the life-cycle of SpawnData is tied to its GSimpleAsyncResult */
  g_simple_async_result_set_op_res_gpointer (data->simple, data, (GDestroyNotify) spawn_data_free);

  error = NULL;
  if (data->cancellable != NULL)
    {
      /* could already be cancelled */
      error = NULL;
      if (g_cancellable_set_error_if_cancelled (data->cancellable, &error))
        {
          g_simple_async_result_take_error (data->simple, error);
          g_simple_async_result_complete_in_idle (data->simple);
          g_object_unref (data->simple);
          goto out;
        }

      data->cancellable_handler_id = g_cancellable_connect (data->cancellable,
                                                            G_CALLBACK (on_cancelled),
                                                            data,
                                                            NULL);
    }

  error = NULL;
  if (!g_shell_parse_argv (data->command_line,
                           &child_argc,
                           &child_argv,
                           &error))
    {
      g_prefix_error (&error,
                      "Error parsing command-line `%s': ",
                      data->command_line);
      g_simple_async_result_take_error (data->simple, error);
      g_simple_async_result_complete_in_idle (data->simple);
      g_object_unref (data->simple);
      goto out;
    }

  error = NULL;
  if (!g_spawn_async_with_pipes (NULL, /* working directory */
                                 child_argv,
                                 NULL, /* envp */
                                 G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
                                 NULL, /* child_setup */
                                 NULL, /* child_setup's user_data */
                                 &(data->child_pid),
                                 NULL, /* gint *stdin_fd */
                                 &(data->child_stdout_fd),
                                 &(data->child_stderr_fd),
                                 &error))
    {
      g_prefix_error (&error,
                      "Error spawning command-line `%s': ",
                      data->command_line);
      g_simple_async_result_take_error (data->simple, error);
      g_simple_async_result_complete_in_idle (data->simple);
      g_object_unref (data->simple);
      goto out;
    }

  if (timeout_seconds > 0)
    {
      data->timeout_source = g_timeout_source_new_seconds (timeout_seconds);
      g_source_set_priority (data->timeout_source, G_PRIORITY_DEFAULT);
      g_source_set_callback (data->timeout_source, timeout_cb, data, NULL);
      g_source_attach (data->timeout_source, data->main_context);
      g_source_unref (data->timeout_source);
    }

  data->child_watch_source = g_child_watch_source_new (data->child_pid);
  g_source_set_callback (data->child_watch_source, (GSourceFunc) child_watch_cb, data, NULL);
  g_source_attach (data->child_watch_source, data->main_context);
  g_source_unref (data->child_watch_source);

  data->child_stdout_channel = g_io_channel_unix_new (data->child_stdout_fd);
  g_io_channel_set_flags (data->child_stdout_channel, G_IO_FLAG_NONBLOCK, NULL);
  data->child_stdout_source = g_io_create_watch (data->child_stdout_channel, G_IO_IN);
  g_source_set_callback (data->child_stdout_source, (GSourceFunc) read_child_stdout, data, NULL);
  g_source_attach (data->child_stdout_source, data->main_context);
  g_source_unref (data->child_stdout_source);

  data->child_stderr_channel = g_io_channel_unix_new (data->child_stderr_fd);
  g_io_channel_set_flags (data->child_stderr_channel, G_IO_FLAG_NONBLOCK, NULL);
  data->child_stderr_source = g_io_create_watch (data->child_stderr_channel, G_IO_IN);
  g_source_set_callback (data->child_stderr_source, (GSourceFunc) read_child_stderr, data, NULL);
  g_source_attach (data->child_stderr_source, data->main_context);
  g_source_unref (data->child_stderr_source);

 out:
  g_strfreev (child_argv);
}
Beispiel #13
0
static void
cockpit_pipe_constructed (GObject *object)
{
  CockpitPipe *self = COCKPIT_PIPE (object);
  GError *error = NULL;

  G_OBJECT_CLASS (cockpit_pipe_parent_class)->constructed (object);

  if (self->priv->in_fd >= 0)
    {
      if (!g_unix_set_fd_nonblocking (self->priv->in_fd, TRUE, &error))
        {
          g_warning ("%s: couldn't set file descriptor to non-blocking: %s",
                     self->priv->name, error->message);
          g_clear_error (&error);
        }

      self->priv->in_source = cockpit_unix_fd_source_new (self->priv->in_fd, G_IO_IN);
      g_source_set_name (self->priv->in_source, "pipe-input");
      g_source_set_callback (self->priv->in_source, (GSourceFunc)dispatch_input, self, NULL);
      g_source_attach (self->priv->in_source, self->priv->context);
    }

  if (self->priv->out_fd >= 0)
    {
      if (!g_unix_set_fd_nonblocking (self->priv->out_fd, TRUE, &error))
        {
          g_warning ("%s: couldn't set file descriptor to non-blocking: %s",
                     self->priv->name, error->message);
          g_clear_error (&error);
        }
      start_output (self);
    }

  if (self->priv->err_fd >= 0)
    {
      if (!g_unix_set_fd_nonblocking (self->priv->err_fd, TRUE, &error))
        {
          g_warning ("%s: couldn't set file descriptor to non-blocking: %s",
                     self->priv->name, error->message);
          g_clear_error (&error);
        }

      self->priv->err_buffer = g_byte_array_new ();
      self->priv->err_source = cockpit_unix_fd_source_new (self->priv->err_fd, G_IO_IN);
      g_source_set_name (self->priv->err_source, "pipe-error");
      g_source_set_callback (self->priv->err_source, (GSourceFunc)dispatch_error, self, NULL);
      g_source_attach (self->priv->err_source, self->priv->context);
    }

  if (self->priv->pid)
    {
      self->priv->is_process = TRUE;

      /* We may need this watch to outlast this process ... */
      self->priv->watch_arg = g_new0 (CockpitPipe *, 1);
      *(self->priv->watch_arg) = self;

      self->priv->child = g_child_watch_source_new (self->priv->pid);
      g_source_set_callback (self->priv->child, (GSourceFunc)on_child_reap,
                             self->priv->watch_arg, g_free);
      g_source_attach (self->priv->child, self->priv->context);
    }
Beispiel #14
0
static void *
glib_ctx_add(void *ctx, const verto_ev *ev, verto_ev_flag *flags)
{
    glib_ev *gev = NULL;
    GIOCondition cond = 0;
    verto_ev_type type = verto_get_type(ev);

    gev = g_new0(glib_ev, 1);
    if (!gev)
        return NULL;

    switch (type) {
        case VERTO_EV_TYPE_IO:
#ifdef WIN32
            gev->chan = g_io_channel_win32_new_socket(verto_get_fd(ev));
#else
            gev->chan = g_io_channel_unix_new(verto_get_fd(ev));
#endif
            if (!gev->chan)
                goto error;
            g_io_channel_set_close_on_unref(gev->chan, FALSE);

            if (*flags & VERTO_EV_FLAG_IO_READ)
                cond |= G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
            if (*flags & VERTO_EV_FLAG_IO_WRITE)
                cond |= G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
            gev->src = g_io_create_watch(gev->chan, cond);
            break;
        case VERTO_EV_TYPE_TIMEOUT:
            gev->src = g_timeout_source_new(verto_get_interval(ev));
            break;
        case VERTO_EV_TYPE_IDLE:
            gev->src = g_idle_source_new();
            break;
        case VERTO_EV_TYPE_CHILD:
            gev->src = g_child_watch_source_new(verto_get_proc(ev));
            *flags &= ~VERTO_EV_FLAG_PERSIST; /* Child events don't persist */
            break;
        case VERTO_EV_TYPE_SIGNAL:
#if GLIB_MAJOR_VERSION >= 2
#if GLIB_MINOR_VERSION >= 29
#ifdef G_OS_UNIX /* Not supported on Windows */
            gev->src = g_unix_signal_source_new(verto_get_signal(ev));
            break;
#endif
#endif /* GLIB_MINOR_VERSION >= 29 */
#endif /* GLIB_MAJOR_VERSION >= 2 */
        default:
            return NULL; /* Not supported */
    }

    if (!gev->src)
        goto error;

    if (type == VERTO_EV_TYPE_IO)
        g_source_set_callback(gev->src, (GSourceFunc) glib_callback_io, (void *) ev, NULL);
    else if (type == VERTO_EV_TYPE_CHILD)
        g_source_set_callback(gev->src, (GSourceFunc) glib_callback_child, (void *) ev, NULL);
    else
        g_source_set_callback(gev->src, glib_callback, (void *) ev, NULL);

    if (*flags & VERTO_EV_FLAG_PRIORITY_HIGH)
        g_source_set_priority(gev->src, G_PRIORITY_HIGH);
    else if (*flags & VERTO_EV_FLAG_PRIORITY_MEDIUM)
        g_source_set_priority(gev->src, G_PRIORITY_DEFAULT_IDLE);
    else if (*flags & VERTO_EV_FLAG_PRIORITY_LOW)
        g_source_set_priority(gev->src, G_PRIORITY_LOW);

    g_source_set_can_recurse(gev->src, FALSE);
    if (g_source_attach(gev->src, ((glib_ev_ctx*) ctx)->context) == 0)
        goto error;

    return gev;

    error:
        if (gev) {
            if (gev->chan)
                g_io_channel_unref(gev->chan);
            if (gev->src) {
                g_source_destroy(gev->src);
                g_source_unref(gev->src);
            }
            g_free(gev);
        }
        return NULL;
}
static gint
nm_openconnect_start_openconnect_binary (NMOPENCONNECTPlugin *plugin,
                                         NMSettingVPN *s_vpn,
                                         GError **error)
{
	NMOPENCONNECTPluginPrivate *priv = NM_OPENCONNECT_PLUGIN_GET_PRIVATE (plugin);
	GPid	pid;
	const char **openconnect_binary = NULL;
	GPtrArray *openconnect_argv;
	GSource *openconnect_watch;
	gint	stdin_fd;
	const char *props_vpn_gw, *props_cookie, *props_cacert, *props_mtu, *props_gwcert, *props_proxy;
	
	/* Find openconnect */
	openconnect_binary = openconnect_binary_paths;
	while (*openconnect_binary != NULL) {
		if (g_file_test (*openconnect_binary, G_FILE_TEST_EXISTS))
			break;
		openconnect_binary++;
	}

	if (!*openconnect_binary) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
		             "%s",
		             _("Could not find openconnect binary."));
		return -1;
	}

	/* The actual gateway to use (after redirection) comes from the auth
	   dialog, so it's in the secrets hash not the properties */
	props_vpn_gw = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GATEWAY);
	if (!props_vpn_gw || !strlen (props_vpn_gw) ) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
		             "%s",
		             _("No VPN gateway specified."));
		return -1;
	}

	props_cookie = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_COOKIE);
	if (!props_cookie || !strlen (props_cookie)) {
		g_set_error (error,
		             NM_VPN_PLUGIN_ERROR,
		             NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
		             "%s",
		             _("No WebVPN cookie provided."));
		return -1;
	}
	props_gwcert = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GWCERT);

	props_cacert = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_CACERT);
	props_mtu = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_MTU);

	props_proxy = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_PROXY);

	openconnect_argv = g_ptr_array_new ();
	g_ptr_array_add (openconnect_argv, (gpointer) (*openconnect_binary));

	if (props_gwcert && strlen(props_gwcert)) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--servercert");
		g_ptr_array_add (openconnect_argv, (gpointer) props_gwcert);
	} else if (props_cacert && strlen(props_cacert)) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--cafile");
		g_ptr_array_add (openconnect_argv, (gpointer) props_cacert);
	}

	if (props_mtu && strlen(props_mtu)) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--mtu");
		g_ptr_array_add (openconnect_argv, (gpointer) props_mtu);
	}

	if (props_proxy && strlen(props_proxy)) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--proxy");
		g_ptr_array_add (openconnect_argv, (gpointer) props_proxy);
	}
		
	g_ptr_array_add (openconnect_argv, (gpointer) "--syslog");
	g_ptr_array_add (openconnect_argv, (gpointer) "--cookie-on-stdin");

	g_ptr_array_add (openconnect_argv, (gpointer) "--script");
	g_ptr_array_add (openconnect_argv, (gpointer) NM_OPENCONNECT_HELPER_PATH);

	priv->tun_name = create_persistent_tundev ();
	if (priv->tun_name) {
		g_ptr_array_add (openconnect_argv, (gpointer) "--interface");
		g_ptr_array_add (openconnect_argv, (gpointer) priv->tun_name);
	}

	g_ptr_array_add (openconnect_argv, (gpointer) props_vpn_gw);

	if (debug)
		g_ptr_array_add (openconnect_argv, (gpointer) "--verbose");

	g_ptr_array_add (openconnect_argv, NULL);

	if (!g_spawn_async_with_pipes (NULL, (char **) openconnect_argv->pdata, NULL,
	                               G_SPAWN_DO_NOT_REAP_CHILD,
	                               openconnect_drop_child_privs, priv->tun_name,
	                               &pid, &stdin_fd, NULL, NULL, error)) {
		g_ptr_array_free (openconnect_argv, TRUE);
		g_warning ("openconnect failed to start.  error: '%s'", (*error)->message);
		return -1;
	}
	g_ptr_array_free (openconnect_argv, TRUE);

	g_message ("openconnect started with pid %d", pid);

	if (write(stdin_fd, props_cookie, strlen(props_cookie)) != strlen(props_cookie) ||
	    write(stdin_fd, "\n", 1) != 1) {
		g_warning ("openconnect didn't eat the cookie we fed it");
		return -1;
	}

	close(stdin_fd);

	NM_OPENCONNECT_PLUGIN_GET_PRIVATE (plugin)->pid = pid;
	openconnect_watch = g_child_watch_source_new (pid);
	g_source_set_callback (openconnect_watch, (GSourceFunc) openconnect_watch_cb, plugin, NULL);
	g_source_attach (openconnect_watch, NULL);
	g_source_unref (openconnect_watch);

	return 0;
}
Beispiel #16
0
void ForkExecParent::start()
{
    if (m_watchChild) {
        SE_THROW("child already started");
    }

    // boost::shared_ptr<ForkExecParent> me = ...;
    GDBusCXX::DBusErrorCXX dbusError;

    SE_LOG_DEBUG(NULL, NULL, "ForkExecParent: preparing for child process %s", m_helper.c_str());
    m_server = GDBusCXX::DBusServerCXX::listen("", &dbusError);
    if (!m_server) {
        dbusError.throwFailure("starting server");
    }
    m_server->setNewConnectionCallback(boost::bind(&ForkExecParent::newClientConnection, this, _2));

    // look for helper binary
    std::string helper;
    GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD;
    if (m_helper.find('/') == m_helper.npos) {
        helper = getEnv("SYNCEVOLUTION_LIBEXEC_DIR", "");
        if (helper.empty()) {
            // env variable not set, look in libexec dir
            helper = SYNCEVO_LIBEXEC;
            helper += "/";
            helper += m_helper;
            if (access(helper.c_str(), R_OK)) {
                // some error, try PATH
                flags = (GSpawnFlags)(flags | G_SPAWN_SEARCH_PATH);
                helper = m_helper;
            }
        } else {
            // use env variable without further checks, must work
            helper += "/";
            helper += m_helper;
        }
    } else {
        // absolute path, use it
        helper = m_helper;
    }

    m_argvStrings.push_back(helper);
    m_argv.reset(AllocStringArray(m_argvStrings));
    for (char **env = environ;
         *env;
         env++) {
        if (!boost::starts_with(*env, ForkExecEnvVar)) {
            m_envStrings.push_back(*env);
        }
    }

    // pass D-Bus address via env variable
    m_envStrings.push_back(ForkExecEnvVar + m_server->getAddress());
    m_env.reset(AllocStringArray(m_envStrings));

    SE_LOG_DEBUG(NULL, NULL, "ForkExecParent: running %s with D-Bus address %s",
                 helper.c_str(), m_server->getAddress().c_str());

    // Check which kind of output redirection is wanted.
    m_mergedStdoutStderr = !m_onOutput.empty();
    if (!m_onOutput.empty()) {
        m_mergedStdoutStderr = true;
    }

    GErrorCXX gerror;
    int err = -1, out = -1;
    if (!g_spawn_async_with_pipes(NULL, // working directory
                                  static_cast<gchar **>(m_argv.get()),
                                  static_cast<gchar **>(m_env.get()),
                                  flags,
                                  // child setup function: redirect stdout to stderr
                                  m_mergedStdoutStderr ? setStdoutToStderr : NULL,
                                  NULL, // child setup user data
                                  &m_childPid,
                                  NULL, // set stdin to /dev/null
                                  (m_mergedStdoutStderr || m_onStdout.empty()) ? NULL : &out,
                                  (m_mergedStdoutStderr || !m_onStderr.empty()) ? &err : NULL,
                                  gerror)) {
        m_childPid = 0;
        gerror.throwError("spawning child");
    }
    // set up output redirection, ignoring failures
    setupPipe(m_err, m_errID, err);
    setupPipe(m_out, m_outID, out);

    SE_LOG_DEBUG(NULL, NULL, "ForkExecParent: child process for %s has pid %ld",
                 helper.c_str(), (long)m_childPid);

    // TODO: introduce C++ wrapper around GSource
    m_watchChild = g_child_watch_source_new(m_childPid);
    g_source_set_callback(m_watchChild, (GSourceFunc)watchChildCallback, this, NULL);
    g_source_attach(m_watchChild, NULL);
}
Beispiel #17
0
/*
 * starts gdb, collects commands and start the first one
 */
gboolean run(const gchar* file, const gchar* commandline, GList* env, GList *witer, GList *biter, const gchar* terminal_device, dbg_callbacks* callbacks)
{
	GError *err = NULL;

	dbg_cbs = callbacks;

	/* spawn GDB */
	const gchar *exclude[] = { "LANG", NULL };
	gchar **gdb_env = utils_copy_environment(exclude, "LANG", "C", NULL);
	if (!g_spawn_async_with_pipes(NULL, (gchar**)gdb_args, gdb_env,
				     GDB_SPAWN_FLAGS, NULL,
				     NULL, &gdb_pid, &gdb_in, &gdb_out, NULL, &err))
	{
		dbg_cbs->report_error(_("Failed to spawn gdb process"));
		return FALSE;
	}
	g_strfreev(gdb_env);
	
	/* move gdb to it's own process group */
	setpgid(gdb_pid, 0);
	
	/* set handler for gdb process exit event */ 
	g_child_watch_add(gdb_pid, on_gdb_exit, NULL);
	gdb_src = g_child_watch_source_new(gdb_pid);

	/* create GDB GIO chanels */
	gdb_ch_in = g_io_channel_unix_new(gdb_in);
	gdb_ch_out = g_io_channel_unix_new(gdb_out);

	/* reading starting gdb messages */
	GList *lines = read_until_prompt();
	GList *line = lines;
	while (line)
	{
		gchar *unescaped = g_strcompress((gchar*)line->data);
		if (strlen(unescaped))
		{
			colorize_message((gchar*)line->data);
		}
		line = line->next;
	}
	g_list_foreach(lines, (GFunc)g_free, NULL);
	g_list_free(lines);

	/* add initial watches to the list */
	while (witer)
	{
		gchar *name = (gchar*)witer->data;

		variable *var = variable_new(name, VT_WATCH);
		watches = g_list_append(watches, var);
		
		witer = witer->next;
	}

	/* collect commands */
	GList *commands = NULL;

	/* loading file */
	GString *command = g_string_new("");
	g_string_printf(command, "-file-exec-and-symbols %s", file);
	commands = add_to_queue(commands, _("~\"Loading target file ...\""), command->str, _("Error loading file"), FALSE);
	g_string_free(command, TRUE);

	/* setting asyncronous mode */
	commands = add_to_queue(commands, NULL, "-gdb-set target-async 1", _("Error configuring GDB"), FALSE);

	/* setting null-stop array printing */
	commands = add_to_queue(commands, NULL, "-interpreter-exec console \"set print null-stop\"", _("Error configuring GDB"), FALSE);

	/* enable pretty printing */
	commands = add_to_queue(commands, NULL, "-enable-pretty-printing", _("Error configuring GDB"), FALSE);

	/* set locale */
	command = g_string_new("");
	g_string_printf(command, "-gdb-set environment LANG=%s", g_getenv("LANG"));
	commands = add_to_queue(commands, NULL, command->str, NULL, FALSE);
	g_string_free(command, TRUE);

	/* set arguments */
	command = g_string_new("");
	g_string_printf(command, "-exec-arguments %s", commandline);
	commands = add_to_queue(commands, NULL, command->str, NULL, FALSE);
	g_string_free(command, TRUE);

	/* set passed evironment */
	GList *iter = env;
	while (iter)
	{
		gchar *name = (gchar*)iter->data;
		iter = iter->next;
		
		gchar *value = (gchar*)iter->data;
	
		command = g_string_new("");
		g_string_printf(command, "-gdb-set environment %s=%s", name, value);

		commands = add_to_queue(commands, NULL, command->str, NULL, FALSE);
		g_string_free(command, TRUE);

		iter = iter->next;
	}

	/* set breaks */
	int bp_index = 1;
	while (biter)
	{
		breakpoint *bp = (breakpoint*)biter->data;
		command = g_string_new("");
		g_string_printf(command, "-break-insert -f %s:%i", bp->file, bp->line);

		GString *error_message = g_string_new("");
		g_string_printf(error_message, _("Breakpoint at %s:%i cannot be set\nDebugger message: %s"), bp->file, bp->line, "%s");
		
		commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE);

		g_string_free(command, TRUE);
		g_string_free(error_message, TRUE);

		if (bp->hitscount)
		{
			command = g_string_new("");
			g_string_printf(command, "-break-after %i %i", bp_index, bp->hitscount);
			commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE);
			g_string_free(command, TRUE);
		}
		if (strlen(bp->condition))
		{
			command = g_string_new("");
			g_string_printf (command, "-break-condition %i %s", bp_index, bp->condition);
			commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE);
			g_string_free(command, TRUE);
		}
		if (!bp->enabled)
		{
			command = g_string_new("");
			g_string_printf (command, "-break-disable %i", bp_index);
			commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE);
			g_string_free(command, TRUE);
		}

		bp_index++;
		biter = biter->next;
	}

	/* set debugging terminal */
	command = g_string_new("-inferior-tty-set ");
	g_string_append(command, terminal_device);
	commands = add_to_queue(commands, NULL, command->str, NULL, FALSE);
	g_string_free(command, TRUE);

	/* connect read callback to the output chanel */
	gdb_id_out = g_io_add_watch(gdb_ch_out, G_IO_IN, on_read_async_output, commands);

	queue_item *item = (queue_item*)commands->data;

	/* send message to debugger messages window */
	if (item->message)
	{
		dbg_cbs->send_message(item->message->str, "grey");
	}

	/* send first command */
	gdb_input_write_line(item->command->str);

	return TRUE;
}
Beispiel #18
0
static void
ul_spawned_job_constructed (GObject *object)
{
  UlSpawnedJob *self = UL_SPAWNED_JOB (object);
  GError *error;
  gchar *cmd;

  G_OBJECT_CLASS (ul_spawned_job_parent_class)->constructed (object);

  cmd = g_strjoinv (" ", self->argv);
  g_debug ("spawned job: %s", cmd);

  self->main_context = g_main_context_get_thread_default ();
  if (self->main_context != NULL)
    g_main_context_ref (self->main_context);

  /* could already be cancelled */
  error = NULL;
  if (g_cancellable_set_error_if_cancelled (ul_job_get_cancellable (UL_JOB (self)), &error))
    {
      emit_completed_with_error_in_idle (self, error);
      g_error_free (error);
      goto out;
    }

  self->cancellable_handler_id = g_cancellable_connect (ul_job_get_cancellable (UL_JOB (self)),
                                                        G_CALLBACK (on_cancelled),
                                                        self,
                                                        NULL);

  error = NULL;
  if (!g_spawn_async_with_pipes (NULL, /* working directory */
                                 self->argv,
                                 NULL, /* envp */
                                 G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
                                 child_setup, /* child_setup */
                                 self, /* child_setup's user_data */
                                 &(self->child_pid),
                                 self->input_string != NULL ? &(self->child_stdin_fd) : NULL,
                                 &(self->child_stdout_fd),
                                 &(self->child_stderr_fd),
                                 &error))
    {
      g_prefix_error (&error, "Error spawning command-line `%s': ", cmd);
      emit_completed_with_error_in_idle (self, error);
      g_error_free (error);
      goto out;
    }

  self->child_watch_source = g_child_watch_source_new (self->child_pid);
  g_source_set_callback (self->child_watch_source, (GSourceFunc) child_watch_cb, self, NULL);
  g_source_attach (self->child_watch_source, self->main_context);
  g_source_unref (self->child_watch_source);

  if (self->child_stdin_fd != -1)
    {
      self->input_string_cursor = self->input_string;

      self->child_stdin_channel = g_io_channel_unix_new (self->child_stdin_fd);
      g_io_channel_set_flags (self->child_stdin_channel, G_IO_FLAG_NONBLOCK, NULL);
      self->child_stdin_source = g_io_create_watch (self->child_stdin_channel, G_IO_OUT);
      g_source_set_callback (self->child_stdin_source, (GSourceFunc) write_child_stdin, self, NULL);
      g_source_attach (self->child_stdin_source, self->main_context);
      g_source_unref (self->child_stdin_source);
    }

  self->child_stdout_channel = g_io_channel_unix_new (self->child_stdout_fd);
  g_io_channel_set_flags (self->child_stdout_channel, G_IO_FLAG_NONBLOCK, NULL);
  self->child_stdout_source = g_io_create_watch (self->child_stdout_channel, G_IO_IN);
  g_source_set_callback (self->child_stdout_source, (GSourceFunc) read_child_stdout, self, NULL);
  g_source_attach (self->child_stdout_source, self->main_context);
  g_source_unref (self->child_stdout_source);

  self->child_stderr_channel = g_io_channel_unix_new (self->child_stderr_fd);
  g_io_channel_set_flags (self->child_stderr_channel, G_IO_FLAG_NONBLOCK, NULL);
  self->child_stderr_source = g_io_create_watch (self->child_stderr_channel, G_IO_IN);
  g_source_set_callback (self->child_stderr_source, (GSourceFunc) read_child_stderr, self, NULL);
  g_source_attach (self->child_stderr_source, self->main_context);
  g_source_unref (self->child_stderr_source);

out:
  g_free (cmd);
}
Beispiel #19
0
static gint
run_command (struct _CamelSExp *f,
             gint argc,
             struct _CamelSExpResult **argv,
             FilterMessageSearch *fms)
{
	CamelMimeMessage *message;
	CamelStream *stream;
	gint i;
	gint pipe_to_child;
	GPid child_pid;
	GError *error = NULL;
	GPtrArray *args;
	child_watch_data_t child_watch_data;
	GSource *source;
	GMainContext *context;

	if (argc < 1 || argv[0]->value.string[0] == '\0')
		return 0;

	args = g_ptr_array_new ();
	for (i = 0; i < argc; i++)
		g_ptr_array_add (args, argv[i]->value.string);
	g_ptr_array_add (args, NULL);

	if (!g_spawn_async_with_pipes (NULL,
				       (gchar **) args->pdata,
				       NULL,
				       G_SPAWN_DO_NOT_REAP_CHILD |
				       G_SPAWN_SEARCH_PATH |
				       G_SPAWN_STDOUT_TO_DEV_NULL |
				       G_SPAWN_STDERR_TO_DEV_NULL,
				       child_setup_func,
				       NULL,
				       &child_pid,
				       &pipe_to_child,
				       NULL,
				       NULL,
				       &error)) {
		g_ptr_array_free (args, TRUE);

		g_set_error (
			fms->error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			_("Failed to create child process '%s': %s"),
			argv[0]->value.string, error->message);
		g_error_free (error);
		return -1;
	}

	g_ptr_array_free (args, TRUE);

	message = camel_filter_search_get_message (fms, f);

	stream = camel_stream_fs_new_with_fd (pipe_to_child);
	camel_data_wrapper_write_to_stream_sync (
		CAMEL_DATA_WRAPPER (message), stream, NULL, NULL);
	camel_stream_flush (stream, NULL, NULL);
	g_object_unref (stream);

	context = g_main_context_new ();
	child_watch_data.loop = g_main_loop_new (context, FALSE);
	g_main_context_unref (context);

	source = g_child_watch_source_new (child_pid);
	g_source_set_callback (source, (GSourceFunc) child_watch, &child_watch_data, NULL);
	g_source_attach (source, g_main_loop_get_context (child_watch_data.loop));
	g_source_unref (source);

	g_main_loop_run (child_watch_data.loop);
	g_main_loop_unref (child_watch_data.loop);

#ifndef G_OS_WIN32
	if (WIFEXITED (child_watch_data.child_status))
		return WEXITSTATUS (child_watch_data.child_status);
	else
		return -1;
#else
	return child_watch_data.child_status;
#endif
}
Beispiel #20
0
static void
spawn_data_free (SpawnData *data)
{
  if (data->timeout_source != NULL)
    {
      g_source_destroy (data->timeout_source);
      data->timeout_source = NULL;
    }

  /* Nuke the child, if necessary */
  if (data->child_watch_source != NULL)
    {
      g_source_destroy (data->child_watch_source);
      data->child_watch_source = NULL;
    }

  if (data->child_pid != 0)
    {
      GSource *source;
      kill (data->child_pid, SIGTERM);
      /* OK, we need to reap for the child ourselves - we don't want
       * to use waitpid() because that might block the calling
       * thread (the child might handle SIGTERM and use several
       * seconds for cleanup/rollback).
       *
       * So we use GChildWatch instead.
       *
       * Avoid taking a references to ourselves. but note that we need
       * to pass the GSource so we can nuke it once handled.
       */
      source = g_child_watch_source_new (data->child_pid);
      g_source_set_callback (source,
                             (GSourceFunc) child_watch_from_release_cb,
                             source,
                             (GDestroyNotify) g_source_destroy);
      g_source_attach (source, data->main_context);
      g_source_unref (source);
      data->child_pid = 0;
    }

  if (data->child_stdout != NULL)
    {
      g_string_free (data->child_stdout, TRUE);
      data->child_stdout = NULL;
    }

  if (data->child_stderr != NULL)
    {
      g_string_free (data->child_stderr, TRUE);
      data->child_stderr = NULL;
    }

  if (data->child_stdout_channel != NULL)
    {
      g_io_channel_unref (data->child_stdout_channel);
      data->child_stdout_channel = NULL;
    }
  if (data->child_stderr_channel != NULL)
    {
      g_io_channel_unref (data->child_stderr_channel);
      data->child_stderr_channel = NULL;
    }

  if (data->child_stdout_source != NULL)
    {
      g_source_destroy (data->child_stdout_source);
      data->child_stdout_source = NULL;
    }
  if (data->child_stderr_source != NULL)
    {
      g_source_destroy (data->child_stderr_source);
      data->child_stderr_source = NULL;
    }

  if (data->child_stdout_fd != -1)
    {
      g_warn_if_fail (close (data->child_stdout_fd) == 0);
      data->child_stdout_fd = -1;
    }
  if (data->child_stderr_fd != -1)
    {
      g_warn_if_fail (close (data->child_stderr_fd) == 0);
      data->child_stderr_fd = -1;
    }

  if (data->cancellable_handler_id > 0)
    {
      g_cancellable_disconnect (data->cancellable, data->cancellable_handler_id);
      data->cancellable_handler_id = 0;
    }

  if (data->main_context != NULL)
    g_main_context_unref (data->main_context);

  if (data->cancellable != NULL)
    g_object_unref (data->cancellable);

  g_free (data->command_line);

  g_slice_free (SpawnData, data);
}