Solved with the following proof of code:
Code:
fusillator@catorcio@1:~/Code/unixprogramming$ cat raise.c
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
volatile sig_atomic_t fatal_error_in_progress = 0;
void myhandler(int sig){
printf("Receiving %u\n", sig);
if (fatal_error_in_progress)
raise (sig);
fatal_error_in_progress=1;
printf("Fatal error in progress\n");
sleep(60);
printf("Handled sig %u\n", sig);
}
int main(void){
printf ("process id %u\n",(int) getpid());
struct sigaction sa;
sa.sa_handler = myhandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGUSR1, &sa, NULL);
sigaction(SIGUSR2, &sa, NULL);
printf("send a SIGUSR1\n");
raise(SIGUSR1);
printf("raised SIGUSR1\n");
}
fusillator@catorcio@1:~/Code/unixprogramming$./raise
process id 2943
send a SIGUSR1
Receiving 10
Fatal error in progress
fusillator@catorcio@2:~/Code/unixprogramming$kill -USR2 2943
fusillator@catorcio@1:~/Code/unixprogramming$./raise
process id 2943
send a SIGUSR1
Receiving 10
Fatal error in progress
Receiving 12
Fatal error in progress
Handled sig 12
Receiving 12
Fatal error in progress
So the signal USR2 interrupts the USR1 handler execution and cause the same handler to be called again for USR2.
Since USR2 signal is locked in this context the call to raise returns immediately putting the signal pending on the process.
The iteration proceeds and when the handler finishes, USR2 is unlocked and the same handler runs again in loop.
The example code of the glibc manual, on which this code is based, handles termination signals and on the last istruction of the handler
terminates the process setting up the signal's handler to the default action
Luca ~
Bookmarks