From b565b6950bbd689be453983e3940235003ffcc45 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Thu, 20 Oct 2011 08:48:36 +0200 Subject: g_unix_signal: Remove g_ prefix to not collide with glib There is a g_unix_signal_new function in glib as well now, but that is only allowed to be used for SIGINT, SIGHUP and SIGTERM, so we have to stay with our own. --- src/unix_signal.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/unix_signal.c (limited to 'src/unix_signal.c') diff --git a/src/unix_signal.c b/src/unix_signal.c new file mode 100644 index 0000000..7577051 --- /dev/null +++ b/src/unix_signal.c @@ -0,0 +1,136 @@ +#define _POSIX_SOURCE +#include +#include +#include "unix_signal.h" + +static GPtrArray *signal_data = NULL; + +typedef struct _UnixSignalData { + guint source_id; + GMainContext *context; + gboolean triggered; + gint signum; +} UnixSignalData; + +typedef struct _UnixSignalSource { + GSource source; + UnixSignalData *data; +} UnixSignalSource; + +static inline UnixSignalData * +unix_signal_data(guint index) +{ + return (UnixSignalData *) g_ptr_array_index(signal_data, index); +} + +static void +handler(gint signum) +{ + g_assert(signal_data != NULL); + for (guint i = 0; i < signal_data->len; ++i) + if (unix_signal_data(i)->signum == signum) + unix_signal_data(i)->triggered = TRUE; + sigaction(signum, &(struct sigaction){handler}, NULL); +} + +static gboolean +check(GSource *source) +{ + UnixSignalSource *signal_source = (UnixSignalSource *) source; + + return signal_source->data->triggered; +} + +static gboolean +prepare(GSource *source, gint *timeout_) +{ + UnixSignalSource *signal_source = (UnixSignalSource*) source; + + if (signal_source->data->context == NULL) { + g_main_context_ref(signal_source->data->context = g_source_get_context(source)); + signal_source->data->source_id = g_source_get_id(source); + } + + *timeout_ = -1; + + return signal_source->data->triggered; +} + +static gboolean +dispatch(GSource *source, GSourceFunc callback, gpointer user_data) +{ + UnixSignalSource *signal_source = (UnixSignalSource *) source; + + signal_source->data->triggered = FALSE; + + return callback(user_data) ? TRUE : FALSE; +} + +static void +finalize(GSource *source) +{ + UnixSignalSource *signal_source = (UnixSignalSource*) source; + + sigaction(signal_source->data->signum, &(struct sigaction){NULL}, NULL); + g_main_context_unref(signal_source->data->context); + g_ptr_array_remove_fast(signal_data, signal_source->data); + if (signal_data->len == 0) + signal_data = (GPtrArray*) g_ptr_array_free(signal_data, TRUE); + g_free(signal_source->data); + +} +static GSourceFuncs SourceFuncs = +{ + .prepare = prepare, + .check = check, + .dispatch = dispatch, + .finalize = finalize, + .closure_callback = NULL, .closure_marshal = NULL +}; + +static void +unix_signal_source_init(GSource *source, gint signum) +{ + UnixSignalSource *signal_source = (UnixSignalSource *) source; + + signal_source->data = g_new(UnixSignalData, 1); + signal_source->data->triggered = FALSE; + signal_source->data->signum = signum; + signal_source->data->context = NULL; + + if (signal_data == NULL) + signal_data = g_ptr_array_new(); + g_ptr_array_add(signal_data, signal_source->data); +} + +GSource * +unix_signal_source_new(gint signum) +{ + GSource *source = g_source_new(&SourceFuncs, sizeof(UnixSignalSource)); + + unix_signal_source_init(source, signum); + sigaction(signum, &(struct sigaction){handler}, NULL); + + return source; +} + +guint +unix_signal_add_full(gint priority, gint signum, GSourceFunc function, gpointer data, GDestroyNotify notify) +{ + g_return_val_if_fail(function != NULL, 0); + GSource *source = unix_signal_source_new(signum); + guint id; + + if (priority != G_PRIORITY_DEFAULT) + g_source_set_priority (source, priority); + g_source_set_callback(source, function, data, notify); + id = g_source_attach(source, NULL); + g_source_unref(source); + + return id; +} + +guint unix_signal_add(gint signum, GSourceFunc function, gpointer data) +{ + return unix_signal_add_full(G_PRIORITY_DEFAULT, signum, function, data, NULL); +} -- cgit