[mousetweaks] Integrate unix signals into the main loop
- From: Gerd Kohlberger <gerdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mousetweaks] Integrate unix signals into the main loop
- Date: Tue, 22 Jun 2010 16:50:34 +0000 (UTC)
commit 4fe76b4312014bf1818a5ea00c9cc9b5af69037c
Author: Gerd Kohlberger <gerdk src gnome org>
Date: Tue Jun 22 18:50:10 2010 +0200
Integrate unix signals into the main loop
src/Makefile.am | 4 +-
src/mt-main.c | 39 ++++++++--
src/mt-sig-handler.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/mt-sig-handler.h | 51 ++++++++++++
4 files changed, 296 insertions(+), 7 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index e3cd2ee..19fd5d4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,7 +32,9 @@ mousetweaks_SOURCES = \
mt-cursor-manager.c \
mt-cursor-manager.h \
mt-listener.c \
- mt-listener.h
+ mt-listener.h \
+ mt-sig-handler.c \
+ mt-sig-handler.h
mousetweaks_CFLAGS = \
$(AM_CFLAGS) \
diff --git a/src/mt-main.c b/src/mt-main.c
index 6ef785b..46faff6 100644
--- a/src/mt-main.c
+++ b/src/mt-main.c
@@ -34,6 +34,7 @@
#include "mt-cursor.h"
#include "mt-main.h"
#include "mt-listener.h"
+#include "mt-sig-handler.h"
enum
{
@@ -606,12 +607,20 @@ cursor_changed (MtCursorManager *manager,
}
static void
-signal_handler (int sig)
+signal_handler (int signal_id)
{
gtk_main_quit ();
}
static void
+mt_main_sig_handler (MtSigHandler *sigh,
+ gint signal_id,
+ gpointer data)
+{
+ signal_handler (signal_id);
+}
+
+static void
gconf_value_changed (GConfClient *client,
const gchar *key,
GConfValue *value,
@@ -853,6 +862,7 @@ mt_main (int argc, char **argv, MtCliArgs cli_args)
MtData *mt;
MtCursorManager *manager;
MtListener *listener;
+ MtSigHandler *sigh;
if (mt_pidfile_create () < 0)
{
@@ -860,13 +870,29 @@ mt_main (int argc, char **argv, MtCliArgs cli_args)
return;
}
- signal (SIGINT, signal_handler);
- signal (SIGTERM, signal_handler);
- signal (SIGQUIT, signal_handler);
- signal (SIGHUP, signal_handler);
-
gtk_init (&argc, &argv);
+ sigh = mt_sig_handler_get_default ();
+ if (mt_sig_handler_setup_pipe (sigh))
+ {
+ mt_sig_handler_catch (sigh, SIGINT);
+ mt_sig_handler_catch (sigh, SIGTERM);
+ mt_sig_handler_catch (sigh, SIGQUIT);
+ mt_sig_handler_catch (sigh, SIGHUP);
+
+ g_signal_connect (sigh, "signal",
+ G_CALLBACK (mt_main_sig_handler), NULL);
+ }
+ else
+ {
+ g_warning ("Couldn't create pipe for signal handling. Using fallback.");
+
+ signal (SIGINT, signal_handler);
+ signal (SIGTERM, signal_handler);
+ signal (SIGQUIT, signal_handler);
+ signal (SIGHUP, signal_handler);
+ }
+
mt = mt_data_init ();
if (!mt)
goto FINISH;
@@ -923,6 +949,7 @@ mt_main (int argc, char **argv, MtCliArgs cli_args)
mt_cursor_manager_restore_all (manager);
g_object_unref (manager);
g_object_unref (listener);
+ g_object_unref (sigh);
CLEANUP:
mt_data_free (mt);
diff --git a/src/mt-sig-handler.c b/src/mt-sig-handler.c
new file mode 100644
index 0000000..2964474
--- /dev/null
+++ b/src/mt-sig-handler.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright © 2010 Gerd Kohlberger <gerdko gmail com>
+ *
+ * This file is part of Mousetweaks.
+ *
+ * Mousetweaks 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.
+ *
+ * Mousetweaks 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/>.
+ */
+
+#include <unistd.h>
+#include <signal.h>
+
+#include "mt-sig-handler.h"
+
+enum
+{
+ SIGNAL,
+ LAST_SIGNAL
+};
+
+struct _MtSigHandlerPrivate
+{
+ GIOChannel *read_chan;
+ guint pipe_set_up : 1;
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+static int _write_fd;
+static int _block_cnt;
+static sigset_t _old_mask;
+
+G_DEFINE_TYPE (MtSigHandler, mt_sig_handler, G_TYPE_OBJECT)
+
+static void
+mt_sig_handler_init (MtSigHandler *sigh)
+{
+ sigh->priv = G_TYPE_INSTANCE_GET_PRIVATE (sigh,
+ MT_TYPE_SIG_HANDLER,
+ MtSigHandlerPrivate);
+ _write_fd = 0;
+ _block_cnt = 0;
+ sigemptyset (&_old_mask);
+}
+
+static void
+mt_sig_handler_finalize (GObject *object)
+{
+ MtSigHandlerPrivate *priv = MT_SIG_HANDLER (object)->priv;
+
+ if (priv->pipe_set_up)
+ {
+ g_io_channel_unref (priv->read_chan);
+ close (_write_fd);
+ }
+
+ G_OBJECT_CLASS (mt_sig_handler_parent_class)->finalize (object);
+}
+
+static void
+mt_sig_handler_class_init (MtSigHandlerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = mt_sig_handler_finalize;
+
+ signals[SIGNAL] =
+ g_signal_new (g_intern_static_string ("signal"),
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE, 1, G_TYPE_INT);
+
+ g_type_class_add_private (klass, sizeof (MtSigHandlerPrivate));
+}
+
+static void
+signal_handler (int signal_id)
+{
+ unsigned char sid;
+ int whtevr;
+
+ sid = (unsigned char) signal_id;
+ whtevr = write (_write_fd, &sid, 1);
+}
+
+static void
+mt_sig_handler_block_signals (void)
+{
+ _block_cnt++;
+
+ if (_block_cnt == 1)
+ {
+ sigset_t mask;
+
+ sigfillset (&mask);
+ sigprocmask (SIG_BLOCK, &mask, &_old_mask);
+ }
+}
+
+static void
+mt_sig_handler_unblock_signals (void)
+{
+ _block_cnt--;
+
+ if (_block_cnt == 0)
+ sigprocmask (SIG_SETMASK, &_old_mask, NULL);
+}
+
+static gboolean
+mt_sig_handler_io_watch (GIOChannel *read_chan,
+ GIOCondition condition,
+ MtSigHandler *sigh)
+{
+ gchar buf[256];
+ gsize bytes_read;
+
+ mt_sig_handler_block_signals ();
+
+ if (g_io_channel_read_chars (read_chan, buf, sizeof (buf),
+ &bytes_read, NULL) == G_IO_STATUS_NORMAL)
+ {
+ gint i, sig_id;
+
+ for (i = 0; i < bytes_read; i++)
+ {
+ sig_id = buf[i];
+ g_signal_emit (sigh, signals[SIGNAL], 0, &sig_id);
+ }
+ }
+
+ mt_sig_handler_unblock_signals ();
+
+ return TRUE;
+}
+
+MtSigHandler *
+mt_sig_handler_get_default (void)
+{
+ static MtSigHandler *sigh = NULL;
+
+ if (!sigh)
+ {
+ sigh = g_object_new (MT_TYPE_SIG_HANDLER, NULL);
+ g_object_add_weak_pointer (G_OBJECT (sigh), (gpointer *) &sigh);
+ }
+ return sigh;
+}
+
+gboolean
+mt_sig_handler_setup_pipe (MtSigHandler *sigh)
+{
+ MtSigHandlerPrivate *priv;
+ int sig_pipe[2];
+
+ g_return_val_if_fail (MT_IS_SIG_HANDLER (sigh), FALSE);
+
+ priv = sigh->priv;
+
+ if (priv->pipe_set_up)
+ {
+ return TRUE;
+ }
+
+ if (pipe (sig_pipe) != 0)
+ {
+ return FALSE;
+ }
+
+ priv->pipe_set_up = TRUE;
+
+ _write_fd = sig_pipe[1];
+
+ priv->read_chan = g_io_channel_unix_new (sig_pipe[0]);
+ g_io_channel_set_flags (priv->read_chan, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_channel_set_encoding (priv->read_chan, NULL, NULL);
+ g_io_channel_set_close_on_unref (priv->read_chan, TRUE);
+ g_io_add_watch (priv->read_chan, G_IO_IN,
+ (GIOFunc) mt_sig_handler_io_watch, sigh);
+
+ g_io_channel_unref (priv->read_chan);
+
+ return TRUE;
+}
+
+void
+mt_sig_handler_catch (MtSigHandler *sigh, int signal_id)
+{
+ struct sigaction action, old;
+
+ g_return_if_fail (MT_IS_SIG_HANDLER (sigh));
+
+ sigemptyset (&action.sa_mask);
+ action.sa_handler = signal_handler;
+ action.sa_flags = 0;
+
+ sigaction (signal_id, &action, &old);
+}
diff --git a/src/mt-sig-handler.h b/src/mt-sig-handler.h
new file mode 100644
index 0000000..dd5eff9
--- /dev/null
+++ b/src/mt-sig-handler.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2010 Gerd Kohlberger <gerdko gmail com>
+ *
+ * This file is part of Mousetweaks.
+ *
+ * Mousetweaks 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.
+ *
+ * Mousetweaks 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 __MT_SIG_HANDLER_H__
+#define __MT_SIG_HANDLER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MT_TYPE_SIG_HANDLER (mt_sig_handler_get_type ())
+#define MT_SIG_HANDLER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MT_TYPE_SIG_HANDLER, MtSigHandler))
+#define MT_IS_SIG_HANDLER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MT_TYPE_SIG_HANDLER))
+
+typedef GObjectClass MtSigHandlerClass;
+typedef struct _MtSigHandler MtSigHandler;
+typedef struct _MtSigHandlerPrivate MtSigHandlerPrivate;
+
+struct _MtSigHandler
+{
+ GObject parent;
+ MtSigHandlerPrivate *priv;
+};
+
+GType mt_sig_handler_get_type (void) G_GNUC_CONST;
+
+MtSigHandler * mt_sig_handler_get_default (void);
+gboolean mt_sig_handler_setup_pipe (MtSigHandler *sigh);
+
+void mt_sig_handler_catch (MtSigHandler *sigh,
+ int signal_id);
+
+G_END_DECLS
+
+#endif /* __MT_SIG_HANDLER_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]