While trying to debug an NTP server on a newly installed Linux system, I came across a problem: the signal SIGALRM was not working on this machine. Take this test program, for instance:
#include <signal.h> #include <stdio.h> void ss(int sig) { printf("Alarmed!\n"); } void main(void) { signal(SIGALRM, ss); printf("Alarming...\n"); raise(SIGALRM); printf("Dealarmed.\n"); sleep(10); }
This program should have produced the following output:
Alarming... Alarmed! Dealarmed.
However, the second line was missing, indicating that the signal handler was never invoked. Using the alarm() function, using sigaction() instead of signal(), or trying to raise a signal asynchronously using the kill command made no difference.
Eventually, I found the cause: the Linux kernel was compiled for a plain Pentium CPU, when in fact the system had a Pentium-MMX processor installed. Changing the processor type and recompiling the kernel was sufficient to fix the problem.
A Footnote
I wrote the above in November, 2004. Two and a half years later, in June 2007, I once again ran into this problem: SIGALRM was blocked for many processes, for no apparent reason. This time around, however, the kernel was not the culprit. SIGALRM was blocked by sshd, but it was not the culprit either; the problem was with inetd that, if its attempt to perform an ident query failed with a timeout, left SIGALRM blocked when it started its child process. This behavior (i.e., the idea that it's not the kernel but some other cause that blocks SIGALRM) can be verified by adding the following lines of code to the beginning of the main() function in the example program above:
sigset_t oldmask, newmask; memset(&newmask, 0, sizeof(newmask)); sigprocmask(SIG_SETMASK, &newmask, &oldmask);