Can signal be ignored (lost)?

Aside from the "too many signals" problem, signals can be explicitly ignored. From man 2 signal:

If the signal signum is delivered to the process, then one of the
following happens:    
  *  If the disposition is set to SIG_IGN, then the signal is ignored.

Signals can also be blocked. From man 7 signal;

A signal may be blocked, which means that it will not be delivered
until it is later unblocked.  Between the time when it is generated
and when it is delivered a signal is said to be pending.

Both blocked and ignored sets of signals are inherited by child processes, so it may happen that the parent process of your application ignored or blocked one of these signals.

What happens when multiple signals are delivered before the process has finished handling previous ones? That depends on the OS. The signal(2) manpage linked above discusses it:

  • System V would reset the signal disposition to the default. Worse, rapid delivery of multiple signals would result in recursive (?) calls.
  • BSD would automatically block the signal until the handler is done.
  • On Linux, this depends on the compilation flags set for GNU libc, but I'd expect the BSD behaviour.

You can't trust that every signal sent will be delivered. For example, the linux kernel "coalesces" SIGCHLD if a process takes a long time in handling SIGCHLD from an exited child process.

To answer another part of your question, signals get "queued" inside the kernel if a number of different signals arrive in too short of an interval.

You should use sigaction() to set up the signal handler with the sa_sigaction member of siginfo_t, setting the sa_mask member of the siginfo_t argument carefully. I think this means masking off all of the "asynch" signals at least. According to the man page for Linux sigaction(), you'll also mask off the signal being handled. I think you should set the sa_flags member to SA_SIGINFO, but I can't remember why I have this superstition. I believe this will get your process a signal handler that stays set with no race conditions, and one that doesn't get interrupted by most other signals.

Write your signal handler function very, very carefully. Basically just set a global variable to indicate that a signal got caught, and have the rest of the process deal with the desired action for that signal. Signals will be masked for the least amount of time that way.

Also, you'll want to test your signal handling code very thoroughly. Put it in a small test process and send as many SIGUSR1 and SIGUSR2 signals as possible, maybe from 2 or 3 special purpose signal-sending programs. Mix in some other signals as well, after you're confidant that your code can handle SIGUSR1 and SIGUSR2 swiftly and correctly. Prepare yourself for difficult debugging.

If you're using linux and only linux, you might think about using signalfd() to create a file descriptor that you can select() or poll to receive those signals. Using signalfd() might make debugging easier.


A signal is guaranteed to be delivered, in the sense that if a process successfully calls kill, then the target will receive the signal. This is asynchronous: the sender has no way to know when the signal is received or processed. However, this does not guarantee that the signal will be delivered. The target could die before it can process the signal. If the target is ignoring the signal at the time it is delivered, the signal will have no effect. If the target receives multiple instances of the same signal number before it can process them, the signals may (and usually are) merged: if you send the same signal twice to a process, you can't know whether the process will receive the signal once or twice. Signals are mostly designed to kill a process or as a way to make a process pay attention, they aren't designed for communication as such.

If you need reliable delivery then you need a different communication mechanism. There are two main communication mechanisms between processes: a pipe allows unidirectional communication; a socket allows bidirectional communication and multiple connections to the same server. If you need the target to process as many notifications as you send it, send bytes over a pipe.

Tags:

Linux

Signals