https://www.securecoding.cert.org/confluence/display/seccode...
Signal handlers will be called in the middle of execution of another function. There's no way to tell what locks may be held or what resources may be allocated/reserved; you can only safely call functions that have been evaluated to be and declared async-safe.
That doesn't give you many options within a signal handler, but it also gives you a very good reason not to use them at all, if you can avoid them.
On the BSDs and Mac OS X you can use kevent to handle signals via EVFILT_SIGNAL, which means you can avoid this mess altogether. On Linux, you have signalfd() which will let you monitor a file descriptor combined with select()/epoll()/etc to handle signals.
I've updated the page, and it was at the end of a long day, so I've probably introduced a raft of new errors and omissions. Now it's all sigaction() all the time, and there is hardly a mention of signal(). I included the async stuff and added sig_atomic_t info.
The complexity of sigaction() et al is pretty high compared to signal(), so I only gave it a glancing blow. I do agree with many posters that there is probably a better way than signals to do whatever it is you're doing. I don't think I've ever used them in real life other than to reap dead children or handle SIGINT. (Of course, people do--it just might not be that common.)
Yes, the old signals are crap. I REALLY have to update that section (which, in my defense, was written about 15 years ago.)