To put it simply: You're wrong and the code is wrong.
Or, you assume that the signal call is superfluous - it isn't, and exists there to make the code behave correctly on platforms that use THE other allowed signal semantics.
Also, the excerpt is not about safe signal handling with signal function;
it is about how to pass an event out from a signal handler - for which there is only one portable way - by changing a variable of type volatile sig_atomic_t. To write safe portable code now, you'd use the function sigaction.
The Linux signal(2) manuals say:
The behavior of signal() varies across UNIX versions, and has also
varied historically across different versions of Linux. Avoid its
use: use sigaction(2) instead.
and
The only portable use of signal() is to set a signal's disposition to SIG_DFL or SIG_IGN.
The semantics when using signal() to establish a signal handler vary across systems (and
POSIX.1 explicitly permits this variation); do not use it for this purpose.
POSIX.1 solved the portability mess by specifying sigaction(2), which
provides explicit control of the semantics when a signal handler is
invoked; use that interface instead of signal().
And
The situation on Linux is as follows:
- The kernel's signal() system call provides System V semantics.
- By default, in glibc 2 and later, the
signal() wrapper function does not invoke the kernel
system call. Instead, it calls sigaction(2) using flags that supply BSD semantics. This
default behavior is provided as long as a suitable feature test macro is defined:
_BSD_SOURCE on glibc 2.19 and earlier or _DEFAULT_SOURCE in glibc 2.19 and later. (By
default, these macros are defined; see feature_test_macros(7) for details.) If such a
feature test macro is not defined, then signal() provides System V semantics.
Now the question is which one is defined. If you compile with -std=c11 you will get the resetting semantics, because it doesn't set the _DEFAULT_SOURCE! And then you need to rearm the SIG_ALARM every time.
The purpose of resetting the signal in the signal handler is that some Unixen clear the handler whenever the signal is triggered. There are also other interesting edge cases - the only reason to use this function is that it is in the C standard, but its behaviour isn't well-specified there either. Never use it to set a custom signal handler.
As the code says, both of these signal calls should be frowned upon. Good modern code shouldmust use sigaction instead, for example
struct sigaction newsigfunc;
newsigfunc.sa_handler = catch_alarm;
sigemptyset(&newsigfunc.sa_mask);
newsigfunc.sa_flags = 0;
sigaction(SIGALRM, &newsigfunc, NULL);
sigaction, unlike signal, will guarantee portability here; wherever it doesn't exist, signal is likely to misbehave too...