signal handler function in multithreaded environment

tommyk picture tommyk · Oct 18, 2012 · Viewed 14.5k times · Source

In my multithreaded GUI application I have the following signal handling code. I want to improve this code so that it will be correct and threading safe but there are some things I don't fully understand in signal handling:

  • is signal handled at the process or thread level (can I have thread-specific signal handlers) ?
  • in which thread context is signal_handler function executed ?
  • is it possible to send many SIGTERM signals in a short time ?
  • does it make sense to use a mutex to prevent parallel execution of signal_handler ?

void signal_handler(int sig)
{
        switch (sig)
        {
        case SIGTERM:
            ::wxLogMessage(wxT("SIGTERM signal received ..."));
            break;
        case SIGINT:
            ::wxLogMessage(wxT("SIGINT signal received ..."));
            break;
        case SIGUSR1:
            ::wxLogMessage(wxT("SIGUSR1 signal received ..."));
            break;
        default:
            ::wxLogMessage(wxT("Unknown signal received ..."));
        }

        // send wxCloseEvent to main application window
        ::wxGetApp().GetTopWindow()->Close(true);
}

I register signal handlers in my init function:

// register signal handlers
signal(SIGTERM, signal_handler);
signal(SIGINT,  signal_handler);
signal(SIGUSR1, signal_handler);

Answer

caf picture caf · Oct 18, 2012
  • Signal handlers are per-process state - that is, all the threads in a process share the same set of installed signal handler functions.
  • Signal masks are per-thread state. Signals can be blocked or unblocked on a per-thread basis.
  • Signals can be process- or thread-directed. If a signal is process-directed, then an arbitrary thread which does not currently have the signal type blocked is chosen to handle it.

A simple way to handle signals in a multi-threaded application is to create one thread as a dedicated signal-handling thread. All signals of interest are blocked in every thread; no signal handlers are established; and the signal-handling thread calls sigwaitinfo() in a loop, acting on the signals as they're received.

This means that you don't need to worry about whether the functions you want to call are async-signal-safe or not, because signals aren't handled in signal handlers - they're handled synchronously by your dedicated signal-handling thread, which can call any function it likes (for example, it can use the ordinary pthreads synchronisation functions to wake up another thread).