#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <math.h>
#include <fcntl.h>
#include <string.h>
#define SIG_MUTEX 1 // prevent mutal interrupt
//#undef SIG_MUTEX
// Print a given set of signals
void affiche_set(sigset_t set,char *msg) {
puts(msg);
for (int sig=0; sig<NSIG; sig++) {
if (sigismember(&set,sig)) { printf("c: \tSignal %s présent\n",strsignal(sig)); }
}
}
// To be called in a signal handler.
// Protect code from being interrupted.
// Show signal mask installed at signal delivery
// Show pending signals while delivery
void common() {
sigset_t toblock, old;
sigfillset(&toblock);
sigprocmask(SIG_SETMASK,&toblock,&old);
affiche_set(old,"c: Blocked signals");
sigset_t set;
sigpending(&set);
affiche_set(set,"c: Pending signals");
sigprocmask(SIG_SETMASK,&old,NULL);
}
// First handler (SIGUSR1)
void f1(int sig) {
printf("c: In %s\n",__FUNCTION__);
common();
printf("c: Out %s\n",__FUNCTION__);
}
// Second handler (SIGUSR2)
void f2(int sig) {
printf("c: In %s\n",__FUNCTION__);
common();
printf("c: Out %s\n",__FUNCTION__);
}
int main(int argc,char *argv[]) {
struct sigaction action;
struct sigaction action2;
struct sigaction old1, old2;
// Install catching before forking to ensure no race condition
action.sa_handler = f1;
sigemptyset(&(action.sa_mask));
#ifdef SIG_MUTEX
sigaddset(&(action.sa_mask),SIGUSR2);
#endif // SIG_MUTEX
action.sa_flags = 0;
sigaction(SIGUSR1,&action,&old1);
action2.sa_handler = f2;
sigemptyset(&(action2.sa_mask));
#ifdef SIG_MUTEX
sigaddset(&(action2.sa_mask),SIGUSR1);
#endif // SIG_MUTEX
action2.sa_flags = 0;
sigaction(SIGUSR2,&action2,&old2);
pid_t pid = fork();
printf("%d\n",pid);
int statut;
switch(pid) {
case 0: // child
while (1) {
printf("c: Do be do be doo\n");
sleep(1);
}
exit(0);
case -1:
fprintf(stderr,"Gosh! Can't demonstrate anything...\n");
exit(1);
default: // ancestor
// restore old behavior
sigaction(SIGUSR1,&old1,NULL);
sigaction(SIGUSR2,&old2,NULL);
sleep(2);
printf("a: sending USR1 %d\n",kill(pid,SIGUSR1));
printf("a: sending USR2 %d\n",kill(pid,SIGUSR2));
sleep(10);
kill(pid,SIGTERM);
pid = waitpid(0,&statut,0);
if (pid==-1) {
fprintf(stderr,"Gosh! something's wrong\n");
exit(1);
}
if (WIFEXITED(statut)) {
printf("a: child %d exit status %d\n",pid,WEXITSTATUS(statut));
}
if (WIFSIGNALED(statut)) {
printf("a: signal %d received by child %d\n",WTERMSIG(statut),pid);
}
break;
}
exit(0);
}