Support This Site burning void logo
 
Blogs:
Reviews
Site Blog
Writers' Exercises
Engineering Ardor
 
Resources:
Roleplaying
Writing
Cooking
Computers
Links
 
Cafepress Shops:
Stuff for Gamers
Caffeinated Chicanery
 
Admin:
Home
About Us
Contact Us
Twilight Time list
Site Update list

Sponsors:


(Your Link Here)
 
Text Link Ads
 
 
Search Now:
In Association with Amazon.com
 
 

Home --> IAQ -->

POSIX Signals

By Jeffrey Howard
All rights reserved unless noted otherwise

 

Posix signals have a lot of associated terminology. Signals can be caught, ignored, blocked, unblocked, handled, and more. In the presence of pthreads, this variety is all the more convoluted by the addition of delivery to threads as well as processes. This document is a gentle introduction to some of the high level concepts and terminology involved.

Platform

This information is based on my understanding of posix signal and thread behavior. If you are using a non-posix compliant version of unix, the general terminology should still be helpful, but the details may be inaccurate.

Introduction

A signal is a kind of notification sent from one process (or the operating system kernel) to another process. Because signals may be sent at any time, they are asynchronous. There are several terms associated with signals.

Delivered
A signal is delivered when it is sent to a process.
Blocked
When signals are blocked, they are not immediately delivered to the process. They wait for the signal to be unblocked. When the block is lifted, any blocked signal is delivered to the process. Signals are not queued, so if a signal is sent more than once while that signal is blocked, it will be delivered only oce after the block is lifted. There are two ways to block a signal. The first is to set a signal mask and mask out a set of signals. Signals also block if the process is executing a signal handler. All signals are blocked until that handler finishes executing.
Caught
A signal is caught using sigaction() or signal() to set up your own function as a signal handler for the signal. So, when the signal is delivered to your process, it is caught and your signal handler, which can be any function with the signature void handler(int signo) is executed. If you set the handler to SIG_DFL, the default signal handler is used.
Ignore
If you set the signal handler to SIG_IGN, the signal will be ignored. You can think of this as being the same as setting the signal handler to a function that immediately exits without doing anything.

Notes

The SIGKILL and SIGSTOP signals cannot be blocked, caught, or ignored.

Threads

The semantics of signals are not changed by using threads, as far as the outside world is concerned. Signals are still delivered to the process as a whole rather than individual threads. This should make intuitive sense. Think of the kill program used to send signals to processes. When you run the command, you give it a process ID number as a command line parameter, but you do not specify which thread in that progam should receive the signal.)

Once inside the process, the signals are delivered to individual threads via the magic of pthreads. One important safety tip is that pthreads constructs like mutexes, condition variables, etc. do not have defined behavior inside signal handlers. So you cannot use pthreads calls or synchronize with other threads while inside a signal handler.

Here it gets a bit complicated. Since you have threads, you can have a few different ways that signals are handled inside the process.

  1. A signal may be sent in reaction to something a thread does. For example, if a particular thread segfaults or divides by zero, the resulting signal is sent directly to the thread that generated the problem.
  2. One thread may deliberately send a signal to another using pthread_kill(). The signal is always sent to the target thread.
  3. There are signals sent from outside the process by the kernel or another process. When one of these signals is delivered to the process, the process sends it to any thread that can handle it. If more than one thread has that signal unblocked, then the thread to handle it is chosen arbitrarily. If you want to have a particular thread handle a signal from outside the system, all other threads in your process must block the signal to force it to go to the one thread you want to handle. If all threads are blocking a signal, the signal waits for the first available thread that unblocks the signal.

Another consideration is that signal actions (handlers called when the signal is caught) are global to the entire process, not particular to any one thread. Thus, while you can block a signal for just one thread, just a few threads, or all threads, you can only choose to ignore a signal for no threads or all threads. Similarly, you can choose which set of threads are not blocking a signal and may handle it, but they all use the same handler for the signal. You are controlling which threads may have to yield time to execute the handler, but you cannot control the handler they will execute on a thread by thread basis. Any thread can use sigaction() to set the handler (or SIG_DFL or SIG_IGN) for a signal.

References

Pthreads Programming, an O'Reilly nutshell book, has about the best coverage of Pthreads, including their signal handling characteristics, that I've seen. (Or, buy from Amazon.)

jhoward@burningvoid.com

 
 
Google
 
Web burningvoid.com

This information is provided "as is," with no warranty or guaranty. The IAQ pages have not been maintained in some time; they're being kept up because, judging by the traffic and link-backs, people still find them useful.
Copyright 1998-2004 by Jeffrey Howard and Heather Grove, except where stated otherwise.