Querying the signal mask

So, we understand that you can set the process's signal mask at the time of sigaction(2) (via the  sa_mask member), or via the sigprocmask(2) system call (as mentioned previously). But how exactly can you query the state of the process signal mask at any arbitrary point in time? 

Well, again, via the sigprocmask(2) system call. But, logically, this API sets a mask, right? This is the trick: if the first parameter set is set to NULL, then the second parameter is effectively ignored, while in the third parameter oldset, the current signal mask value is populated, and thus we can query the signal mask without altering it.

The ch11/query_mask program demonstrates this, the code is built upon our previous example sig2.c. Hence, we do not need to show the entire source; we just show the relevant code, in main():

[...]
/* Init sigaction:
* setup 'my_handler' as the signal handler function,
* trap just the SIGINT and SIGQUIT signals.
*/
memset(&act, 0, sizeof(act));
act.sa_handler = my_handler;
/* This is interesting: we fill the signal mask, implying that
* _all_ signals are masked (blocked) while the signal handler
* runs! */
sigfillset(&act.sa_mask);

if (sigaction(SIGINT, &act, 0) < 0)
FATAL("sigaction on SIGINT failed");
if (sigaction(SIGQUIT, &act, 0) < 0)
FATAL("sigaction on SIGQUIT failed");
[...]

As you can see, this time we use the sigfillset(3) (one of the useful POSIX signal set operations or sigsetops(3) operators) to populate the signal mask with all 1's, implying that, while the signal handler code is running, all signals will be masked (blocked).

Here is the relevant portion of the signal handler code:

static void my_handler(int signum)
{
const char *str1 = "*** my_handler: handled SIGINT *** ";
const char *str2 = "*** my_handler: handled SIGQUIT *** ";

show_blocked_signals();
switch (signum) {
[...]

Ah! Here, the intelligence is within the show_blocked_signals function; we have this function in our common code source file: ../common.c. Here's the function:

/*
* Signaling: Prints (to stdout) all signal integer values that are
* currently in the Blocked (masked) state.
*/
int show_blocked_signals(void)
{
sigset_t oldset;
int i, none=1;

/* sigprocmask:
* int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
* if 'set' is NULL, the 'how' is ignored, but the
* 'oldset' sigmask value is populated; thus we can query the
* signal mask without altering it.
*/
sigemptyset(&oldset);
if (sigprocmask(SIG_UNBLOCK, 0, &oldset) < 0)
return -1;

printf(" [SigBlk: ");
for (i=1; i<=64; i++) {
if (sigismember(&oldset, i)) {
none=0;
printf("%d ", i);
}
}
if (none)
printf("-none-] ");
else
printf("] ");
fflush(stdout);
return 0;
}

The key here is this: the sigprocmask(2) is used with a NULL second parameter (the mask to set); hence, as stated earlier, the how parameter is ignored and the value-result third parameter oldset will hold the current process signal mask.

We can query each signal bit in the bitmask using, again, the sigsetops: sigismember(3) convenience method. Now all that's left to do is iterate over each bit in the mask and print the signal number, if the bit is set, or ignore it if it is cleared.

Here's the output of a test run:

$ make query_mask 
gcc -Wall -c ../common.c -o common.o
gcc -Wall -c -o query_mask.o query_mask.c
gcc -Wall -o query_mask query_mask.c common.o
$ ./query_mask
Looping, iteration #01 ...
Looping, iteration #02 ...
Looping, iteration #03 ...
^C
[SigBlk: 1 2 3 4 5 6 7 8 10 11 12 13 14 15 16 17 18 20 21 22 23 24 25 26 27 28 29 30 31 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ]
*** my_handler: handled SIGINT ***
Looping, iteration #04 ...
Looping, iteration #05 ...
^
[SigBlk: 1 2 3 4 5 6 7 8 10 11 12 13 14 15 16 17 18 20 21 22 23 24 25 26 27 28 29 30 31 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ]
*** my_handler: handled SIGQUIT ***
Looping, iteration #06 ...
Looping, iteration #07 ...
^Z
[2]+ Stopped ./query_mask
$ kill %2
[2]+ Terminated ./query_mask
$

Notice how the blocked signals are printed out. Hey, can you spot the missing signals?

SIGKILL(#9) and SIGSTOP(#19) cannot be masked; also, signals 32 and 33 are internally reserved for and used by the Pthreads implementation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.136.18.61