[gnome-terminal] client: legacy: Implement waiting for child process exit
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-terminal] client: legacy: Implement waiting for child process exit
- Date: Mon, 30 Oct 2017 21:41:50 +0000 (UTC)
commit 42f9f7978e3d103af7a5c9eb2c8f0e8d40e0647c
Author: Christian Persch <chpe src gnome org>
Date: Mon Oct 30 22:41:06 2017 +0100
client: legacy: Implement waiting for child process exit
Add --wait to make the client wait until the child process exits, and
then exit the client with the same exit status.
This of course only works if only creating one terminal, not
when creating multiple terminals at once.
src/terminal-options.c | 41 +++++++++++++++++++++++++++---
src/terminal-options.h | 2 +
src/terminal.c | 64 +++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 99 insertions(+), 8 deletions(-)
---
diff --git a/src/terminal-options.c b/src/terminal-options.c
index ee9e1b4..ffe39fd 100644
--- a/src/terminal-options.c
+++ b/src/terminal-options.c
@@ -728,6 +728,28 @@ option_working_directory_callback (const gchar *option_name,
}
static gboolean
+option_wait_cb (const gchar *option_name,
+ const gchar *value,
+ gpointer data,
+ GError **error)
+{
+ TerminalOptions *options = data;
+
+ if (options->any_wait) {
+ g_set_error_literal (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
+ _("Can only use --wait once"));
+ return FALSE;
+ }
+
+ options->any_wait = TRUE;
+
+ InitialTab *it = ensure_top_tab (options);
+ it->wait = TRUE;
+
+ return TRUE;
+}
+
+static gboolean
option_pass_std_cb (const gchar *option_name,
const gchar *value,
gpointer data,
@@ -957,6 +979,7 @@ terminal_options_parse (const char *working_directory,
options->default_title = NULL;
options->zoom = 1.0;
options->zoom_set = FALSE;
+ options->any_wait = FALSE;
options->screen_number = -1;
options->default_working_dir = g_strdup (working_directory);
@@ -1001,11 +1024,12 @@ terminal_options_parse (const char *working_directory,
retval = g_option_context_parse (context, argcp, argvp, error);
g_option_context_free (context);
- if (retval)
- return options;
+ if (!retval) {
+ terminal_options_free (options);
+ return NULL;
+ }
- terminal_options_free (options);
- return NULL;
+ return options;
}
/**
@@ -1349,6 +1373,15 @@ get_goption_context (TerminalOptions *options)
N_("DIRNAME")
},
{
+ "wait",
+ 0,
+ G_OPTION_FLAG_NO_ARG,
+ G_OPTION_ARG_CALLBACK,
+ option_wait_cb,
+ N_("Wait until the child exits"),
+ NULL
+ },
+ {
"stdin",
0,
G_OPTION_FLAG_HIDDEN | G_OPTION_FLAG_NO_ARG,
diff --git a/src/terminal-options.h b/src/terminal-options.h
index 1d120b5..d2945e2 100644
--- a/src/terminal-options.h
+++ b/src/terminal-options.h
@@ -92,6 +92,7 @@ typedef struct
char *sm_config_prefix;
guint zoom_set : 1;
+ guint any_wait : 1;
} TerminalOptions;
typedef struct
@@ -106,6 +107,7 @@ typedef struct
GArray *fd_array;
guint zoom_set : 1;
guint active : 1;
+ guint wait : 1;
} InitialTab;
typedef struct
diff --git a/src/terminal.c b/src/terminal.c
index 41e5341..05aef55 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
+#include <sys/wait.h>
#include <glib.h>
#include <glib/gstdio.h>
@@ -45,6 +46,50 @@
GS_DEFINE_CLEANUP_FUNCTION0(TerminalOptions*, gs_local_options_free, terminal_options_free)
#define gs_free_options __attribute__ ((cleanup(gs_local_options_free)))
+/* Wait-for-exit helper */
+
+typedef struct {
+ GMainLoop *loop;
+ int status;
+} RunData;
+
+static void
+receiver_child_exited_cb (TerminalReceiver *receiver,
+ int status,
+ RunData *data)
+{
+ data->status = status;
+
+ if (g_main_loop_is_running (data->loop))
+ g_main_loop_quit (data->loop);
+}
+
+static int
+run_receiver (TerminalReceiver *receiver)
+{
+ RunData data = { g_main_loop_new (NULL, FALSE), 0 };
+ gulong id = g_signal_connect (receiver, "child-exited",
+ G_CALLBACK (receiver_child_exited_cb), &data);
+ g_main_loop_run (data.loop);
+ g_signal_handler_disconnect (receiver, id);
+ g_main_loop_unref (data.loop);
+
+ /* Mangle the exit status */
+ int exit_code;
+ if (WIFEXITED (data.status))
+ exit_code = WEXITSTATUS (data.status);
+ else if (WIFSIGNALED (data.status))
+ exit_code = 128 + (int) WTERMSIG (data.status);
+ else if (WCOREDUMP (data.status))
+ exit_code = 127;
+ else
+ exit_code = 127;
+
+ return exit_code;
+}
+
+/* Factory helpers */
+
static gboolean
get_factory_exit_status (const char *message,
const char *service_name,
@@ -197,7 +242,7 @@ handle_show_preferences (const char *service_name)
* @options: a #TerminalOptions
* @allow_resume: whether to merge the terminal configuration from the
* saved session on resume
- * @error: a #GError to fill in
+ * @wait_for_receiver: location to store the #TerminalReceiver to wait for
*
* Processes @options. It loads or saves the terminal configuration, or
* opens the specified windows and tabs.
@@ -208,7 +253,8 @@ handle_show_preferences (const char *service_name)
static gboolean
handle_options (TerminalFactory *factory,
const char *service_name,
- TerminalOptions *options)
+ TerminalOptions *options,
+ TerminalReceiver **wait_for_receiver)
{
GList *lw;
const char *encoding;
@@ -300,7 +346,7 @@ handle_options (TerminalFactory *factory,
receiver = terminal_receiver_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
- G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+ (it->wait ? 0 :
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS),
options->server_app_id ?
options->server_app_id
:
TERMINAL_APPLICATION_ID,
object_path,
@@ -338,6 +384,9 @@ handle_options (TerminalFactory *factory,
else
continue; /* Continue processing the remaining options! */
}
+
+ if (it->wait)
+ gs_transfer_out_value (wait_for_receiver, &receiver);
}
}
@@ -413,7 +462,14 @@ main (int argc, char **argv)
goto out;
}
- if (handle_options (factory, service_name, options))
+ TerminalReceiver *receiver = NULL;
+ if (!handle_options (factory, service_name, options, &receiver))
+ goto out;
+
+ if (receiver != NULL) {
+ exit_code = run_receiver (receiver);
+ g_object_unref (receiver);
+ } else
exit_code = EXIT_SUCCESS;
out:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]