Home > Blockchain >  Trying to randomly send signal from parent to child process in a loop
Trying to randomly send signal from parent to child process in a loop

Time:12-04

I'm trying to have it execute in a loop where the parent randomly picks between SIGUSR1 and SIGUSR2 and send it to the child process to receive and write to a file

My problem is the signal will only send in the first loop and after that it stops

int main(int argc, char* argv[], char *envp[]){
    time_t start, finish; //for example purposes, to save the time
    
    struct sigaction sact; //signal action structure
    sact.sa_handler = &handler;
    sact.sa_handler = &handler2;
    sigset_t new_set, old_set; //signal mask data-types
    FILE *file = fopen("received_signal.txt", "w");
    fprintf(file,"%s\t %s\t %s\n", "Signal Type", 
    "Signal Time", "thread ID");
    fclose(file);
    
    int pid;
    int cpid;
    pid = fork();

    if(pid == 0){//recieves
        //sigaction(SIGUSR1, &sact, NULL);
        while(1){
       
            signal(SIGUSR1, handler);
            signal(SIGUSR2, handler2);
 
            sleep(1);
    
        
        }
    } else{ //generates 
        while(1){
   
            sleep(1); // give child time to spawn
            printf("hello\n");
            parent_func(0);

            
            //wait(NULL);
            usleep(((rand() % 5)   1) * 10000);
        }
    }
    
    return 0;
}


void parent_func(int child_pid){
    srand(time(NULL));
    int rnd = rand();
    int result = (rnd & 1) ? 2 : 1;

    struct timeval t;
    gettimeofday(&t, NULL);
    unsigned long time = 1000000 * t.tv_sec   t.tv_usec;
    printf("result: %d\n", result);
    printf("time: %ld\n", time);

    if(result == 1){
        //sigaction(SIGUSR1, &sact, NULL);
        kill(child_pid, SIGUSR1);
        log(SIGUSR1);
    } else{
        //sigaction(SIGUSR2, &sact, NULL);
        kill(child_pid, SIGUSR2);
        log(SIGUSR2);
    }
}

void handler(int sig){
    if (sig == SIGUSR1){
        puts("child received SIGUSR1");
    }

    
}
void handler2(int sig){
    if (sig == SIGUSR2){
        puts("child received SIGUSR2");
    }
    
}

Tried throwing the child in a while loop to get it to repeat but no such luck

CodePudding user response:

man signal(2) tells you that the handler is reset to SIG_DFL once a signal is delivered:

If the disposition is set to a function, then first either the disposition is reset to SIG_DFL, or the signal is blocked (see Portability below), and then handler is called with argument signum. If invocation of the handler caused the signal to be blocked, then the signal is unblocked upon return from the handler.

I suggest you use sigaction instead of signal:

#define _XOPEN_SOURCE 500
#define _POSIX_C_SOURCE 199309L
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>

void handler(int sig) {
    char s[] = "child received signal SIGUSR?\n";
    char *s2 = strchr(s, '?');
    *s2 = sig == SIGUSR1 ? '1' : '2';
    write(STDOUT_FILENO, s, strlen(s));
}

int main(int argc, char* argv[], char *envp[]){
    pid_t child_pid = fork();
    if(!child_pid) {
        struct sigaction sa = {
            .sa_handler = &handler
        };
        sigaction(SIGUSR1, &sa, NULL);
        sigaction(SIGUSR2, &sa, NULL);
        for(;;) {
            sleep(1);
        }
        return 0;
    }
    for(;;) {
        sleep(1);
        int s = (int []){SIGUSR1, SIGUSR2}[rand() % 2];
        printf("parent sending signal %d to %d\n", s, child_pid);
        kill(child_pid, s);
    }
}

and sample output:

parent sending signal 12 to 521586
child received signal SIGUSR2
parent sending signal 10 to 521586
child received signal SIGUSR1
parent sending signal 12 to 521586
child received signal SIGUSR2
parent sending signal 12 to 521586
child received signal SIGUSR2
  • Related