Commit 883eb1f4 authored by Christian Hergert's avatar Christian Hergert

sandboxing: add subprocess abstraction

To support Building applications while running from inside the sandbox, we
need to allow breaking out of the sandbox for such tooling. For example,
we want to run the build tooling for flatpaks from the host system (since
we wont have sufficient privileges inside the sandbox).

This abstracts our use of GSubprocess so that we can have multiple
implementations. Sadly, since GSubprocess is not an interface, we cannot
simply create an alternate implementation.

There are two implementations of the abstraction. IdeSimpleSubprocess is
just a wrapper around GSubprocess (since our API is almost identical).
Additionally, we have IdeHostProcess which is a process that runs within
the host system, via the --allow=devel support in flatpak. Also required
--talk-name=org.freedesktop.Flatpak.
parent e2ccf178
......@@ -124,6 +124,8 @@ libide_1_0_la_public_headers = \
sourceview/ide-source-style-scheme.h \
sourceview/ide-source-view-mode.h \
sourceview/ide-source-view.h \
subprocess/ide-subprocess.h \
subprocess/ide-subprocess-launcher.h \
symbols/ide-symbol-node.h \
symbols/ide-symbol-resolver.h \
symbols/ide-symbol-tree.h \
......@@ -175,7 +177,6 @@ libide_1_0_la_public_headers = \
workbench/ide-workbench-addin.h \
workbench/ide-workbench-header-bar.h \
workbench/ide-workbench.h \
workers/ide-subprocess-launcher.h \
workers/ide-worker.h \
$(NULL)
......@@ -287,6 +288,8 @@ libide_1_0_la_public_sources = \
sourceview/ide-source-style-scheme.c \
sourceview/ide-source-view-mode.c \
sourceview/ide-source-view.c \
subprocess/ide-subprocess.c \
subprocess/ide-subprocess-launcher.c \
symbols/ide-symbol-node.c \
symbols/ide-symbol-resolver.c \
symbols/ide-symbol-tree.c \
......@@ -326,7 +329,6 @@ libide_1_0_la_public_sources = \
workbench/ide-workbench-header-bar.c \
workbench/ide-workbench-open.c \
workbench/ide-workbench.c \
workers/ide-subprocess-launcher.c \
workers/ide-worker.c \
$(NULL)
......@@ -416,6 +418,11 @@ libide_1_0_la_SOURCES = \
sourceview/ide-text-iter.h \
sourceview/ide-text-util.c \
sourceview/ide-text-util.h \
subprocess/ide-breakout-subprocess.c \
subprocess/ide-breakout-subprocess.h \
subprocess/ide-breakout-subprocess-private.h \
subprocess/ide-simple-subprocess.c \
subprocess/ide-simple-subprocess.h \
theatrics/ide-box-theatric.c \
theatrics/ide-box-theatric.h \
theming/ide-css-provider.c \
......
......@@ -24,7 +24,8 @@
#include "buildsystem/ide-build-result.h"
#include "buildsystem/ide-environment.h"
#include "runtimes/ide-runtime.h"
#include "workers/ide-subprocess-launcher.h"
#include "subprocess/ide-subprocess.h"
#include "subprocess/ide-subprocess-launcher.h"
typedef struct
{
......@@ -46,17 +47,17 @@ ide_build_command_wait_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GSubprocess *subprocess = (GSubprocess *)object;
IdeSubprocess *subprocess = (IdeSubprocess *)object;
g_autoptr(GTask) task = user_data;
GError *error = NULL;
IDE_ENTRY;
g_assert (G_IS_SUBPROCESS (subprocess));
g_assert (IDE_IS_SUBPROCESS (subprocess));
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (G_IS_TASK (task));
if (!g_subprocess_wait_finish (subprocess, result, &error))
if (!ide_subprocess_wait_finish (subprocess, result, &error))
{
g_task_return_error (task, error);
IDE_EXIT;
......@@ -121,7 +122,7 @@ ide_build_command_real_run (IdeBuildCommand *self,
{
IdeBuildCommandPrivate *priv = ide_build_command_get_instance_private (self);
g_autoptr(IdeSubprocessLauncher) launcher = NULL;
g_autoptr(GSubprocess) subprocess = NULL;
g_autoptr(IdeSubprocess) subprocess = NULL;
gboolean ret;
IDE_ENTRY;
......@@ -147,7 +148,7 @@ ide_build_command_real_run (IdeBuildCommand *self,
ide_build_result_log_subprocess (build_result, subprocess);
ret = g_subprocess_wait (subprocess, cancellable, error);
ret = ide_subprocess_wait (subprocess, cancellable, error);
IDE_RETURN (ret);
}
......@@ -163,7 +164,7 @@ ide_build_command_real_run_async (IdeBuildCommand *self,
{
IdeBuildCommandPrivate *priv = ide_build_command_get_instance_private (self);
g_autoptr(IdeSubprocessLauncher) launcher = NULL;
g_autoptr(GSubprocess) subprocess = NULL;
g_autoptr(IdeSubprocess) subprocess = NULL;
g_autoptr(GTask) task = NULL;
GError *error = NULL;
......@@ -201,10 +202,10 @@ ide_build_command_real_run_async (IdeBuildCommand *self,
ide_build_result_log_subprocess (build_result, subprocess);
g_subprocess_wait_async (subprocess,
cancellable,
ide_build_command_wait_cb,
g_steal_pointer (&task));
ide_subprocess_wait_async (subprocess,
cancellable,
ide_build_command_wait_cb,
g_steal_pointer (&task));
IDE_EXIT;
}
......@@ -214,10 +215,16 @@ ide_build_command_real_run_finish (IdeBuildCommand *self,
GAsyncResult *result,
GError **error)
{
gboolean ret;
IDE_ENTRY;
g_assert (IDE_IS_BUILD_COMMAND (self));
g_assert (G_IS_TASK (result));
return g_task_propagate_boolean (G_TASK (result), error);
ret = g_task_propagate_boolean (G_TASK (result), error);
IDE_RETURN (ret);
}
static IdeBuildCommand *
......
......@@ -530,6 +530,7 @@ ide_build_manager_build_cb (GObject *object,
if (build_result == NULL)
{
IDE_TRACE_MSG ("%s", error->message);
g_task_return_error (task, error);
IDE_GOTO (failure);
}
......
......@@ -29,6 +29,7 @@
#include "buildsystem/ide-build-result-addin.h"
#include "diagnostics/ide-source-location.h"
#include "files/ide-file.h"
#include "subprocess/ide-subprocess.h"
#define POINTER_MARK(p) GSIZE_TO_POINTER(GPOINTER_TO_SIZE(p)|1)
#define POINTER_UNMARK(p) GSIZE_TO_POINTER(GPOINTER_TO_SIZE(p)&~(gsize)1)
......@@ -351,27 +352,27 @@ ide_build_result_tail_into (IdeBuildResult *self,
void
ide_build_result_log_subprocess (IdeBuildResult *self,
GSubprocess *subprocess)
IdeSubprocess *subprocess)
{
IdeBuildResultPrivate *priv = ide_build_result_get_instance_private (self);
GInputStream *stdout_stream;
GInputStream *stderr_stream;
g_return_if_fail (IDE_IS_BUILD_RESULT (self));
g_return_if_fail (G_IS_SUBPROCESS (subprocess));
g_return_if_fail (IDE_IS_SUBPROCESS (subprocess));
/* ensure lazily created streams are available */
(void)ide_build_result_get_stderr_stream (self);
(void)ide_build_result_get_stdout_stream (self);
stderr_stream = g_subprocess_get_stderr_pipe (subprocess);
stderr_stream = ide_subprocess_get_stderr_pipe (subprocess);
if (stderr_stream)
ide_build_result_tail_into (self,
IDE_BUILD_RESULT_LOG_STDERR,
stderr_stream,
priv->stderr_writer);
stdout_stream = g_subprocess_get_stdout_pipe (subprocess);
stdout_stream = ide_subprocess_get_stdout_pipe (subprocess);
if (stdout_stream)
ide_build_result_tail_into (self,
IDE_BUILD_RESULT_LOG_STDOUT,
......
......@@ -60,7 +60,7 @@ struct _IdeBuildResultClass
GInputStream *ide_build_result_get_stdout_stream (IdeBuildResult *result);
GInputStream *ide_build_result_get_stderr_stream (IdeBuildResult *result);
void ide_build_result_log_subprocess (IdeBuildResult *result,
GSubprocess *subprocess);
IdeSubprocess *subprocess);
GTimeSpan ide_build_result_get_running_time (IdeBuildResult *self);
gboolean ide_build_result_get_running (IdeBuildResult *self);
void ide_build_result_set_running (IdeBuildResult *self,
......
......@@ -457,12 +457,16 @@ ide_configuration_manager_queue_writeback (IdeConfigurationManager *self)
{
g_assert (IDE_IS_CONFIGURATION_MANAGER (self));
IDE_ENTRY;
if (self->writeback_handler != 0)
g_source_remove (self->writeback_handler);
self->writeback_handler = g_timeout_add_seconds (WRITEBACK_TIMEOUT_SECS,
ide_configuration_manager_do_writeback,
self);
IDE_EXIT;
}
static void
......
......@@ -122,6 +122,9 @@ typedef struct _IdeSourceSnippets IdeSourceSnippets;
typedef struct _IdeSourceSnippetsManager IdeSourceSnippetsManager;
typedef struct _IdeSubprocess IdeSubprocess;
typedef struct _IdeSubprocessLauncher IdeSubprocessLauncher;
typedef struct _IdeSymbol IdeSymbol;
typedef struct _IdeSymbolResolver IdeSymbolResolver;
......
......@@ -115,6 +115,8 @@ G_BEGIN_DECLS
#include "sourceview/ide-source-map.h"
#include "sourceview/ide-source-style-scheme.h"
#include "sourceview/ide-source-view.h"
#include "subprocess/ide-subprocess.h"
#include "subprocess/ide-subprocess-launcher.h"
#include "symbols/ide-symbol-resolver.h"
#include "symbols/ide-symbol.h"
#include "symbols/ide-tags-builder.h"
......@@ -148,7 +150,6 @@ G_BEGIN_DECLS
#include "workbench/ide-workbench-addin.h"
#include "workbench/ide-workbench-header-bar.h"
#include "workbench/ide-workbench.h"
#include "workers/ide-subprocess-launcher.h"
#undef IDE_INSIDE
......
......@@ -27,13 +27,16 @@
#include "runner/ide-runner.h"
#include "runner/ide-runner-addin.h"
#include "workers/ide-subprocess-launcher.h"
#include "subprocess/ide-subprocess.h"
#include "subprocess/ide-subprocess-launcher.h"
typedef struct
{
PeasExtensionSet *addins;
GQueue argv;
IdeEnvironment *env;
GSubprocessFlags flags;
guint run_on_host : 1;
} IdeRunnerPrivate;
typedef struct
......@@ -46,6 +49,7 @@ enum {
PROP_0,
PROP_ARGV,
PROP_ENV,
PROP_RUN_ON_HOST,
N_PROPS
};
......@@ -98,14 +102,16 @@ ide_runner_run_wait_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GSubprocess *subprocess = (GSubprocess *)object;
IdeSubprocess *subprocess = (IdeSubprocess *)object;
g_autoptr(GTask) task = user_data;
GError *error = NULL;
IdeRunner *self;
IDE_ENTRY;
g_assert (G_IS_SUBPROCESS (subprocess));
g_assert (IDE_IS_SUBPROCESS (subprocess));
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (G_IS_TASK (task));
self = g_task_get_source_object (task);
......@@ -113,17 +119,17 @@ ide_runner_run_wait_cb (GObject *object,
g_signal_emit (self, signals [EXITED], 0);
if (!g_subprocess_wait_finish (subprocess, result, &error))
if (!ide_subprocess_wait_finish (subprocess, result, &error))
{
g_task_return_error (task, error);
IDE_EXIT;
}
if (g_subprocess_get_if_exited (subprocess))
if (ide_subprocess_get_if_exited (subprocess))
{
gint exit_code;
exit_code = g_subprocess_get_exit_status (subprocess);
exit_code = ide_subprocess_get_exit_status (subprocess);
if (exit_code == EXIT_SUCCESS)
{
......@@ -150,7 +156,7 @@ ide_runner_real_run_async (IdeRunner *self,
IdeRunnerPrivate *priv = ide_runner_get_instance_private (self);
g_autoptr(GTask) task = NULL;
g_autoptr(IdeSubprocessLauncher) launcher = NULL;
g_autoptr(GSubprocess) subprocess = NULL;
g_autoptr(IdeSubprocess) subprocess = NULL;
g_auto(GStrv) environ = NULL;
const gchar *identifier;
GError *error = NULL;
......@@ -163,7 +169,10 @@ ide_runner_real_run_async (IdeRunner *self,
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, ide_runner_real_run_async);
launcher = ide_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
launcher = ide_subprocess_launcher_new (priv->flags);
ide_subprocess_launcher_set_run_on_host (launcher, priv->run_on_host);
ide_subprocess_launcher_set_clear_env (launcher, FALSE);
environ = g_get_environ (); /* We still rely on many system vars like DISPLAY */
ide_subprocess_launcher_set_environ (launcher, (const gchar * const *)environ);
......@@ -176,7 +185,7 @@ ide_runner_real_run_async (IdeRunner *self,
subprocess = ide_subprocess_launcher_spawn_sync (launcher, cancellable, &error);
g_assert (subprocess == NULL || G_IS_SUBPROCESS (subprocess));
g_assert (subprocess == NULL || IDE_IS_SUBPROCESS (subprocess));
if (subprocess == NULL)
{
......@@ -184,14 +193,14 @@ ide_runner_real_run_async (IdeRunner *self,
IDE_GOTO (failure);
}
identifier = g_subprocess_get_identifier (subprocess);
identifier = ide_subprocess_get_identifier (subprocess);
g_signal_emit (self, signals [SPAWNED], 0, identifier);
g_subprocess_wait_async (subprocess,
cancellable,
ide_runner_run_wait_cb,
g_steal_pointer (&task));
ide_subprocess_wait_async (subprocess,
cancellable,
ide_runner_run_wait_cb,
g_steal_pointer (&task));
failure:
IDE_EXIT;
......@@ -302,6 +311,10 @@ ide_runner_get_property (GObject *object,
g_value_set_object (value, ide_runner_get_environment (self));
break;
case PROP_RUN_ON_HOST:
g_value_set_boolean (value, ide_runner_get_run_on_host (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
......@@ -321,6 +334,10 @@ ide_runner_set_property (GObject *object,
ide_runner_set_argv (self, g_value_get_boxed (value));
break;
case PROP_RUN_ON_HOST:
ide_runner_set_run_on_host (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
......@@ -353,6 +370,13 @@ ide_runner_class_init (IdeRunnerClass *klass)
IDE_TYPE_ENVIRONMENT,
(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
properties [PROP_RUN_ON_HOST] =
g_param_spec_boolean ("run-on-host",
"Run on Host",
"Run on Host",
FALSE,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties);
signals [EXITED] =
......@@ -386,6 +410,7 @@ ide_runner_init (IdeRunner *self)
g_queue_init (&priv->argv);
priv->env = ide_environment_new ();
priv->flags = 0;
}
/**
......@@ -728,3 +753,39 @@ ide_runner_new (IdeContext *context)
"context", context,
NULL);
}
gboolean
ide_runner_get_run_on_host (IdeRunner *self)
{
IdeRunnerPrivate *priv = ide_runner_get_instance_private (self);
g_return_val_if_fail (IDE_IS_RUNNER (self), FALSE);
return priv->run_on_host;
}
void
ide_runner_set_run_on_host (IdeRunner *self,
gboolean run_on_host)
{
IdeRunnerPrivate *priv = ide_runner_get_instance_private (self);
run_on_host = !!run_on_host;
if (run_on_host != priv->run_on_host)
{
priv->run_on_host = run_on_host;
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_RUN_ON_HOST]);
}
}
void
ide_runner_set_flags (IdeRunner *self,
GSubprocessFlags flags)
{
IdeRunnerPrivate *priv = ide_runner_get_instance_private (self);
g_return_if_fail (IDE_IS_RUNNER (self));
priv->flags = flags;
}
......@@ -47,26 +47,31 @@ struct _IdeRunnerClass
GError **error);
};
IdeRunner *ide_runner_new (IdeContext *context);
void ide_runner_force_quit (IdeRunner *self);
void ide_runner_run_async (IdeRunner *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean ide_runner_run_finish (IdeRunner *self,
GAsyncResult *result,
GError **error);
void ide_runner_prepend_argv (IdeRunner *self,
const gchar *param);
void ide_runner_append_argv (IdeRunner *self,
const gchar *param);
gchar **ide_runner_get_argv (IdeRunner *self);
void ide_runner_set_argv (IdeRunner *self,
const gchar * const *argv);
IdeEnvironment *ide_runner_get_environment(IdeRunner *self);
GInputStream *ide_runner_get_stdin (IdeRunner *self);
GOutputStream *ide_runner_get_stdout (IdeRunner *self);
GOutputStream *ide_runner_get_stderr (IdeRunner *self);
IdeRunner *ide_runner_new (IdeContext *context);
void ide_runner_force_quit (IdeRunner *self);
IdeEnvironment *ide_runner_get_environment (IdeRunner *self);
void ide_runner_run_async (IdeRunner *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean ide_runner_run_finish (IdeRunner *self,
GAsyncResult *result,
GError **error);
void ide_runner_set_flags (IdeRunner *self,
GSubprocessFlags flags);
void ide_runner_prepend_argv (IdeRunner *self,
const gchar *param);
void ide_runner_append_argv (IdeRunner *self,
const gchar *param);
gchar **ide_runner_get_argv (IdeRunner *self);
void ide_runner_set_argv (IdeRunner *self,
const gchar * const *argv);
GInputStream *ide_runner_get_stdin (IdeRunner *self);
GOutputStream *ide_runner_get_stdout (IdeRunner *self);
GOutputStream *ide_runner_get_stderr (IdeRunner *self);
gboolean ide_runner_get_run_on_host (IdeRunner *self);
void ide_runner_set_run_on_host (IdeRunner *self,
gboolean run_on_host);
G_END_DECLS
......
......@@ -25,7 +25,7 @@
#include "buildsystem/ide-build-target.h"
#include "runner/ide-runner.h"
#include "workers/ide-subprocess-launcher.h"
#include "subprocess/ide-subprocess-launcher.h"
G_BEGIN_DECLS
......
/* ide-breakout-subprocess-private.h
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef IDE_BREAKOUT_SUBPROCESS_PRIVATE_H
#define IDE_BREAKOUT_SUBPROCESS_PRIVATE_H
#include "subprocess/ide-breakout-subprocess.h"
G_BEGIN_DECLS
IdeSubprocess *_ide_breakout_subprocess_new (const gchar *cwd,
const gchar * const *argv,
const gchar * const *env,
GSubprocessFlags flags,
gboolean clear_flags,
GCancellable *cancellable,
GError **error) G_GNUC_INTERNAL;
G_END_DECLS
#endif /* IDE_BREAKOUT_SUBPROCESS_PRIVATE_H */
This diff is collapsed.
/* GIO - GLib Input, Output and Streaming Library
*
* Copyright © 2012, 2013, 2016 Red Hat, Inc.
* Copyright © 2012, 2013 Canonical Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the licence or (at
* your option) any later version.
*
* See the included COPYING file for more information.
*
* Authors: Christian Hergert <chergert@redhat.com>
*/
#ifndef IDE_BREAKOUT_SUBPROCESS_H
#define IDE_BREAKOUT_SUBPROCESS_H
#include "subprocess/ide-subprocess.h"
G_BEGIN_DECLS
#define IDE_TYPE_BREAKOUT_SUBPROCESS (ide_breakout_subprocess_get_type())
G_DECLARE_FINAL_TYPE (IdeBreakoutSubprocess, ide_breakout_subprocess, IDE, BREAKOUT_SUBPROCESS, GObject)
G_END_DECLS
#endif /* IDE_BREAKOUT_SUBPROCESS_H */
/* ide-simple-subprocess.c
*
* Copyright (C) 2016 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "ide-simple-subprocess"
#include "ide-simple-subprocess.h"
struct _IdeSimpleSubprocess
{
GObject parent_instance;
GSubprocess *subprocess;
};
static void subprocess_iface_init (IdeSubprocessInterface *iface);
G_DEFINE_TYPE_EXTENDED (IdeSimpleSubprocess, ide_simple_subprocess, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE (IDE_TYPE_SUBPROCESS, subprocess_iface_init))
static void
ide_simple_subprocess_finalize (GObject *object)
{
IdeSimpleSubprocess *self = (IdeSimpleSubprocess *)object;
g_clear_object (&self->subprocess);
G_OBJECT_CLASS (ide_simple_subprocess_parent_class)->finalize (object);
}
static void
ide_simple_subprocess_class_init (IdeSimpleSubprocessClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = ide_simple_subprocess_finalize;
}
static void
ide_simple_subprocess_init (IdeSimpleSubprocess *self)
{
}
#define WRAP_INTERFACE_METHOD(name, ...) \
g_subprocess_##name(IDE_SIMPLE_SUBPROCESS(subprocess)->subprocess, ## __VA_ARGS__)
static const gchar *
ide_simple_subprocess_get_identifier (IdeSubprocess *subprocess)
{
return WRAP_INTERFACE_METHOD (get_identifier);
}
static GInputStream *
ide_simple_subprocess_get_stdout_pipe (IdeSubprocess *subprocess)
{
return WRAP_INTERFACE_METHOD (get_stdout_pipe);
}
static GInputStream *
ide_simple_subprocess_get_stderr_pipe (IdeSubprocess *subprocess)
{
return WRAP_INTERFACE_METHOD (get_stderr_pipe);
}
static GOutputStream *
ide_simple_subprocess_get_stdin_pipe (IdeSubprocess *subprocess)
{
return WRAP_INTERFACE_METHOD (get_stdin_pipe);
}
static gboolean
ide_simple_subprocess_wait (IdeSubprocess *subprocess,
GCancellable *cancellable,
GError **error)
{
return WRAP_INTERFACE_METHOD (wait, cancellable, error);
}
static void
ide_simple_subprocess_wait_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GSubprocess *subprocess = (GSubprocess *)object;
g_autoptr(GTask) task = user_data;
g_autoptr(GError) error = NULL;
if (!g_subprocess_wait_finish (subprocess, result, &error))
g_task_return_error (task, g_steal_pointer (&error));
else
g_task_return_boolean (task, TRUE);
}
static void
ide_simple_subprocess_wait_async (IdeSubprocess *subprocess,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
IdeSimpleSubprocess *self = (IdeSimpleSubprocess *)subprocess;
GTask *task = g_task_new (self, cancellable, callback, user_data);
g_subprocess_wait_async (self->subprocess, cancellable, ide_simple_subprocess_wait_cb, task);
}
static gboolean
ide_simple_subprocess_wait_finish (IdeSubprocess *subprocess,
GAsyncResult *result,
GError **error)
{
return g_task_propagate_boolean (G_TASK (result), error);
}
static gboolean
ide_simple_subprocess_get_successful (IdeSubprocess *subprocess)
{
return WRAP_INTERFACE_METHOD (get_successful);
}
static gboolean
ide_simple_subprocess_get_if_exited (IdeSubprocess *subprocess)
{
return WRAP_INTERFACE_METHOD (get_if_exited);
}
static gint
ide_simple_subprocess_get_exit_status (IdeSubprocess *subprocess)
{
return WRAP_INTERFACE_METHOD (get_exit_status);
}
static gboolean
ide_simple_subprocess_get_if_signaled (IdeSubprocess *subprocess)
{
return WRAP_INTERFACE_METHOD (get_if_signaled);
}
static gint
ide_simple_subprocess_get_term_sig (IdeSubprocess *subprocess)
{
return WRAP_INTERFACE_METHOD (get_term_sig);
}
static gint
ide_simple_subprocess_get_status (IdeSubprocess *subprocess)
{
return WRAP_INTERFACE_METHOD (get_status);
}
static void
ide_simple_subprocess_send_signal (IdeSubprocess *subprocess,
gint signal_num)
{
return WRAP_INTERFACE_METHOD (send_signal, signal_num);
}
static void
ide_simple_subprocess_force_exit (IdeSubprocess *subprocess)