[virt-tools-list] [PATCH 1/3] remote-viewer: add handler for SIGINT signal

Francesco Giudici fgiudici at redhat.com
Tue Nov 12 11:29:10 UTC 2019


When remote-viewer is started from terminal, CTRL-C sends a SIGINT
signal to the program causing immediate termination.
Catch the signal in order to properly shutdown remote-viewer once the
application is started.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1713311

Signed-off-by: Francesco Giudici <fgiudici at redhat.com>
---
 src/virt-viewer-app.c | 79 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/src/virt-viewer-app.c b/src/virt-viewer-app.c
index da8cfa9..06e237b 100644
--- a/src/virt-viewer-app.c
+++ b/src/virt-viewer-app.c
@@ -36,6 +36,7 @@
 #include <glib/gprintf.h>
 #include <glib/gi18n.h>
 #include <errno.h>
+#include <fcntl.h>
 
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
@@ -1756,6 +1757,74 @@ static gboolean opt_fullscreen = FALSE;
 static gboolean opt_kiosk = FALSE;
 static gboolean opt_kiosk_quit = FALSE;
 
+#ifndef G_OS_WIN32
+static int sigint_pipe[2];
+
+static void
+sigint_handler(int signum)
+{
+    int savedErrno;
+
+    g_return_if_fail(signum == SIGINT);
+
+    savedErrno = errno;
+    if (write(sigint_pipe[1], "x", 1) == -1 && errno != EAGAIN)
+        g_debug("SIGINT handler failure\n");
+    errno = savedErrno;
+}
+
+static void
+register_sigint_handler()
+{
+    int flags, i;
+    struct sigaction sa;
+
+    if (pipe(sigint_pipe) == -1)
+        goto err;
+
+    for (i = 0; i < 2; i++) {
+        flags = fcntl(sigint_pipe[i], F_GETFL);
+        if (flags == -1)
+            goto err;
+        flags |= O_NONBLOCK;
+        if (fcntl(sigint_pipe[i], F_SETFL, flags) == -1)
+            goto err;
+    }
+
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = SA_RESTART;
+    sa.sa_handler = sigint_handler;
+    if (sigaction(SIGINT, &sa, NULL) == -1)
+        goto err;
+
+    return;
+
+err:
+    g_debug("Cannot register SIGINT handler\n");
+}
+
+static gboolean
+sigint_cb(GIOChannel *source,
+          GIOCondition condition,
+          gpointer data)
+{
+    VirtViewerApp *self = VIRT_VIEWER_APP(data);
+    VirtViewerAppPrivate *priv = self->priv;
+    gchar sbuf;
+
+    g_assert(condition == G_IO_IN);
+
+    g_debug("got SIGINT, quitting\n");
+    if (priv->started)
+        virt_viewer_app_quit(self);
+    else
+        exit(0);
+
+    g_io_channel_read_chars (source, &sbuf, 1, NULL, NULL);
+    return TRUE;
+}
+#endif
+
 static void
 title_maybe_changed(VirtViewerApp *self, GParamSpec* pspec G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED)
 {
@@ -1766,10 +1835,20 @@ static void
 virt_viewer_app_init(VirtViewerApp *self)
 {
     GError *error = NULL;
+#ifndef G_OS_WIN32
+    GIOChannel *sigint_channel = NULL;
+#endif
+
     self->priv = virt_viewer_app_get_instance_private(self);
 
     gtk_window_set_default_icon_name("virt-viewer");
 
+#ifndef G_OS_WIN32
+    register_sigint_handler();
+    sigint_channel = g_io_channel_unix_new(sigint_pipe[0]);
+    g_io_add_watch(sigint_channel, G_IO_IN, sigint_cb, self);
+#endif
+
     self->priv->displays = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
     self->priv->config = g_key_file_new();
     self->priv->config_file = g_build_filename(g_get_user_config_dir(),
-- 
2.21.0





More information about the virt-tools-list mailing list