This page is about writing signal handlers, which is a way to execute code when signals are delivered. If you're getting a signal that you don't understand or your application is terminating unexpectedly, see SignalsSentOnCrash.
Signals are delivered asynchronously, much like interrupts, and so there are a great deal of restrictions placed on the code which runs. Many of these restrictions are much like ThreadSafety, in that you have to account for the fact that your signal handler could run at any moment while other code is running, causing weird problems.
If the signal handler is invoked while the main function is in the middle of this update process, an increment will be lost. Let's try to fix this by adding a simple lock. We'll assume that we have a TestAndSet? function which atomically sets a variable to 1 and returns its old value.
If we were working with threads, then everything would work as expected. But with signals, this not only fails to solve the problem, but it actually makes it worse.
My first exposure to this kind of problem was when I learned about interrupts, writing code with Turbo C++ in Jr. High. The cardinal rule I learned was: "In your signal handler, never do anything other than setting a global variable." There are many reasons for this, some of which are touched on in the article. All your classic mutual exclusion problems raise their ugly heads, and they even bring a few new friends (like stack overflows) along too. Really, with most signals, all you want to know is "did the signal happen recently or not." Setting a global is enough to tell you that. If you want to do anything else, you'd better have a damn good understanding of how the underlying hardware and OS work. Or else you'll be creating Heisenbugs so fast it'll make your head spin.