简体   繁体   中英

process communication with signls

I am trying to write a C program which has some number of processes. One of them sends a random signal in the range SIGRTMIN and SIGRTMAX to all other processes but I want this signal will be ignored in main process.I used the global variable to have randomized signal to ignore with SIG_IGN. It looks It is not helping because the main stops with real-time signal when wants to ignore the first randomized signal.

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>

volatile sig_atomic_t disarming_signal = 0;

void disarming_handler (int sig) {
     disarming_signal = sig;
     fprintf(stderr,"signal %d is handeled", disarming_signal);
}
int rand_range(int min_n, int max_n){
     int rand_n = rand() % (max_n - min_n) + min_n;
     return rand_n;
}
int sethandler (void (*f)(int), int sigNo) {
    struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = f;
    if (-1==sigaction(sigNo, &act, NULL))
        return -1;
return 0;
}
void sigchld_handler(int sig){ 
pid_t pid;
for(;;){
    pid=waitpid(0, NULL, WNOHANG);
    if(pid==0) return;
    if(pid<=0) {
        if(errno==ECHILD) return;
        perror("waitpid:");
        exit(EXIT_FAILURE);
    }
}
}

void usage(){
fprintf(stderr,"USAGE: sappartherroryst n\n");
fprintf(stderr,"n - number of Therrorysts\n");
}

void therroryst_work(){
int s,k,t;
srand(getpid());
s = rand_range(SIGRTMIN, SIGRTMAX);
t = rand_range(10, 20);
k = t;  
if(sethandler(disarming_handler, s)){
    perror("Seting therroryst handeler");
    exit(EXIT_FAILURE);
}

fprintf(stderr, "[%d] I am therroryst. My disarming signal is [%d]. I will wait [%d] Sec.\n", getpid(), s, t);
while(k>0) {
    k=sleep(k);
    if(disarming_signal == s){
        fprintf(stderr, "I got signal [%d]\n.",disarming_signal);
         return ;
    }
}
fprintf(stderr, "[%d] KABOOM\n",getpid());
exit(EXIT_SUCCESS);
}
void create_therrorysts(int n){
while(n-->0){
    switch(fork()) {
        case 0:
            therroryst_work();
            exit(EXIT_SUCCESS);
        case -1:
            perror("Fork():");
            exit(EXIT_FAILURE);
    }
}
} 
void sapper_work(){
int sig_dis, i; 
struct timespec t, tn = {1,0};
fprintf(stderr,"[%d] I am sapper.\n", getpid());
for(i=0;i<10;i++){
    for(t=tn;nanosleep(&t,&t););
    sig_dis = rand_range(SIGRTMIN, SIGRTMAX);   
    if(kill(0, sig_dis)<0){
        perror("Disarming_send\n");
        exit(EXIT_FAILURE);
    }

fprintf(stderr,"I sended signal [%d].\n",sig_dis);  
disarming_signal = sig_dis;
}
fprintf(stderr, "end of sending");
exit(EXIT_SUCCESS);
}

void create_sapper(){
switch(fork()) {
    case 0:
        sapper_work();
        exit(EXIT_SUCCESS);
    case -1:
        perror("Fork():");
        exit(EXIT_FAILURE);
}
}
int main(int argc, char** argv){
int n;
pid_t pid;

if(argc != 2){
    usage();
    return EXIT_FAILURE;
}
n = atoi(argv[1]);  

if(n <= 0){ 
    usage();
    return EXIT_FAILURE;
}

if(sethandler(sigchld_handler, SIGCHLD)) {
    perror("Seting parent SIGCHLD:");
    exit(EXIT_FAILURE);
}
create_therrorysts(n);
create_sapper();
sleep(5);
for(;;) {
    if(sethandler(SIG_IGN, disarming_signal)){
        perror("Seting parent disarming111");
        exit(EXIT_FAILURE);
    }
}

for(;;){
    pid=wait(NULL);
    if(pid<0)
        switch (errno){
            case ECHILD:
                return EXIT_SUCCESS;
            case EINTR: 
                continue;
            default:
                perror("wait:");
                exit(EXIT_FAILURE);
        }
}

return EXIT_SUCCESS;
} 

You have sleep(5) after the create_sapper and before sethandler(IGN). That means it's very likely that the signal is sent before your main process has ignored it.

EDIT: Adding comment from Jonathan Leffler into this answer as it is equally (or even more) important:

There's also a problem with setting the signal handler even if you put the sleep() after that loop - the parent doesn't get to see what the child chooses as disarming_signal.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM