source: signal.c @ 257b9c4

release-1.8release-1.9
Last change on this file since 257b9c4 was 3535a6e, checked in by David Benjamin <davidben@mit.edu>, 10 years ago
First go at sigwait-based signal handling Instead of relying on pselect and signal masking to listen for signals, which glib doesn't support, we spawn a dedicated signal thread that loops in sigwait. These signals are posted back to the main message loop which may handle them at will. This avoids the need for complex reentrant code and sig_atomic_t. This removes the final pre-select action. SIGINT doesn't quite work right yet because we can no longer take it in the middle of an event loop iteration.
  • Property mode set to 100644
File size: 1.6 KB
Line 
1#include <glib.h>
2#include <pthread.h>
3#include <signal.h>
4#include <stdio.h>
5#include <stdlib.h>
6
7static GThread *signal_thread;
8static sigset_t signal_set;
9
10static void (*signal_cb)(int, void*);
11static void *signal_cbdata;
12
13static gpointer signal_thread_func(gpointer data);
14static gboolean signal_thunk(gpointer data);
15
16void owl_signal_init(const sigset_t *set, void (*callback)(int, void*), void *data) {
17  GError *error = NULL;
18
19  signal_set = *set;
20  signal_cb = callback;
21  signal_cbdata = data;
22  /* Block these signals in all threads, so we can get them. */
23  pthread_sigmask(SIG_BLOCK, set, NULL);
24  /* Spawn a dedicated thread to sigwait. */
25  signal_thread = g_thread_create(signal_thread_func, g_main_context_default(),
26                                  FALSE, &error);
27  if (signal_thread == NULL) {
28    fprintf(stderr, "Failed to create signal thread: %s\n", error->message);
29    exit(1);
30  }
31}
32
33static gpointer signal_thread_func(gpointer data) {
34  GMainContext *context = data;
35
36  while (1) {
37    GSource *source;
38    int signal;
39    int ret;
40
41    ret = sigwait(&signal_set, &signal);
42    /* TODO: Print an error? man page claims it never errors. */
43    if (ret != 0)
44      continue;
45
46    /* Send a message to the other main. */
47    source = g_idle_source_new();
48    g_source_set_priority(source, G_PRIORITY_DEFAULT);
49    g_source_set_callback(source, signal_thunk, GINT_TO_POINTER(signal), NULL);
50    g_source_attach(source, context);
51    g_source_unref(source);
52  }
53  return NULL;
54}
55
56static gboolean signal_thunk(gpointer data) {
57  signal_cb(GPOINTER_TO_INT(data), signal_cbdata);
58  return FALSE;
59}
Note: See TracBrowser for help on using the repository browser.