Changeset a7fac14 for signal.c


Ignore:
Timestamp:
Jul 23, 2011, 7:30:51 PM (13 years ago)
Author:
David Benjamin <davidben@mit.edu>
Branches:
master, release-1.10, release-1.9
Children:
4ebbfbc, 85bb19b, d933c3ca
Parents:
f661cee
git-author:
David Benjamin <davidben@mit.edu> (07/20/11 02:03:42)
git-committer:
David Benjamin <davidben@mit.edu> (07/23/11 19:30:51)
Message:
Assign all watched signals to a dummy no-op disposition

Otherwise some (namely SIGWINCH) may have SIG_DFL = SIG_IGN. This means
that the signal is ignored if the signal thread is in the middle of
processing another signal (a race condition), and on Solaris it's not
delivered at all.

Also more consistently consider errors in setup here fatal. And rename
CHECK_RESULT to OR_DIE.

Reported-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Adam Glasgall <adam@crossproduct.net>
File:
1 edited

Legend:

Unmodified
Added
Removed
  • signal.c

    r1d21d9f ra7fac14  
    11#include <errno.h>
     2#include <glib.h>
    23#include <pthread.h>
    34#include <signal.h>
     
    1314static void *signal_thread_func(void *data);
    1415
    15 /* Initializes the signal thread to listen for 'set' on a dedicated
     16static void dummy_handler(int signum)
     17{
     18  /* Do nothing. This should never get called. It'd be nice to report the error
     19   * or something, but you can't have nice things in a signal handler. */
     20}
     21
     22#define OR_DIE(s, syscall)       \
     23  G_STMT_START {                 \
     24    if ((syscall) == -1) {       \
     25      perror((s));               \
     26      exit(1);                   \
     27    }                            \
     28  } G_STMT_END
     29
     30/* Initializes the signal thread to listen for 'signals' on a dedicated
    1631 * thread. 'callback' is called *on the signal thread* when a signal
    1732 * is received.
     
    1934 * This function /must/ be called before any other threads are
    2035 * created. (Otherwise the signals will not get blocked correctly.) */
    21 void owl_signal_init(const sigset_t *set, void (*callback)(const siginfo_t*, void*), void *data) {
     36void owl_signal_init(const int *signals, int num_signals, void (*callback)(const siginfo_t*, void*), void *data) {
     37  struct sigaction sig_dummy = { .sa_handler = dummy_handler };
    2238  int ret;
     39  int i;
    2340
    24   signal_set = *set;
    2541  signal_cb = callback;
    2642  signal_cbdata = data;
     43
     44  /* Stuff the signals into our sigset_t. Also assign all of them to a dummy
     45   * handler. Otherwise, if their default is SIG_IGN, they will get dropped if
     46   * delivered while processing. On Solaris, they will not get delivered at
     47   * all. */
     48  OR_DIE("sigemptyset", sigemptyset(&signal_set));
     49  for (i = 0; i < num_signals; i++) {
     50    OR_DIE("sigaddset", sigaddset(&signal_set, signals[i]));
     51    OR_DIE("sigaction", sigaction(signals[i], &sig_dummy, NULL));
     52  }
     53
    2754  /* Block these signals in all threads, so we can get them. */
    28   if ((ret = pthread_sigmask(SIG_BLOCK, set, NULL)) != 0) {
     55  if ((ret = pthread_sigmask(SIG_BLOCK, &signal_set, NULL)) != 0) {
    2956    errno = ret;
    3057    perror("pthread_sigmask");
     58    exit(1);
    3159  }
    3260  /* Spawn a dedicated thread to sigwait. */
Note: See TracChangeset for help on using the changeset viewer.