This filter is used when you want to see what signals are being set to a process. You can only use it on “yourself”, ie not other processes. It provides a way of performing some action on a signal without using a signal handler. This example demonstrates three things.
In the code we have a handler for SIGQUIT and we ignore SIGINT. The handler for SIGQUIT will print out when it is called and set a flag, caught, to 1.
Lets have a look at the kevent processing:
i = kevent(kq, NULL, 0, ke, 1, &timeout);
if (i == -1) /*< Line 55 */
if (errno == EINTR)
continue;
else
err(1, "kevent!"); /*< Line 59 */
else if (i == 0) /*< Line 60 */
printf("timeout, caught = %d!\n", caught); /*< Line 61 */
else {
if (ke[0].ident == SIGQUIT) { /*< Line 63 */
printf("SIGQUIT sent, caught = %d\n", caught);
caught = 0; /*< Line 65 */
} else if (ke[0].ident == SIGINT) /*< Line 66 */
printf("SIGINT sent\n"); /*< Line 67 */
else /*< Unreachable */
printf("strange signal %d\n", ke[0].ident);
}
Note in the call to kevent we pass in a timeout, which is set to 2 seconds, to the call will block for that long each time. Since we’re dealing with signals the call to kevent may return -1 with errno set to EINTR, in which case we want to keep running, otherwise we quit (lines 55 - 59).
If kevent returns 0, it means the timeout was reached and we just print out the current value of caught (lines 60 & 61).
Otherwise we inspect the ident to determine the signal we receieved (in this example ke is an array of 2 kevent structures). If we receieved SIGQUIT, we print out the fact that we have and value of caught, then reset it back to 0 (lines 63 - 65). Otherwise we have been sent SIGINT (which we are ignoring) so print out that we have (lines 66 - 67). The other 2 lines (68 - 69) are impossible to reach, they are there for symmetry and clarity.
This is the signal handler for SIGQUIT
void
sigquit(int sig)
{
#define str "in sig handler\n"
write(STDOUT_FILENO, str, sizeof(str));
#undef str
caught = 1;
}
Dirty cpp hacks aside, we see it prints out that it has been called and that it sets caught to 1.
So lets see it run. Other code ensures the kevent processing loop will only run 10 times, due to SIGQUIT and SIGING being otherwise incapacitated.
$ stty quit ^\\
$ stty intr ^C
$ ./signal
timeout, caught = 0! #wait a few seconds
^CSIGINT sent #hit ^C a few times
^CSIGINT sent
timeout, caught = 0! #wait some more
^\in sig handler #hit ^\, handler sets caught to 1
SIGQUIT sent, caught = 1
timeout, caught = 0! #wait and see caught has been reset
^\in sig handler #hit ^\
SIGQUIT sent, caught = 1
timeout, caught = 0!
exiting
$
We can see here the affect of the timeout, with kevent returning 0 a few times. Secondly, we see that we still get notification of SIGINT being sent even though it is being ignored, and thirdly, we see the signal handler will run before the kevent is returned.