0

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

  • Please update program with includes and missing functions (log). – Allan Wind Dec 03 '22 at 05:16
  • You use the time() function but then declare a variable named time, too. – Allan Wind Dec 03 '22 at 05:18
  • 1
    `sact.sa_handler = &handler; sact.sa_handler = handler2;` cannot possible be correct. – Allan Wind Dec 03 '22 at 05:23
  • See [How to avoid using `printf()` in a signal handler?](https://stackoverflow.com/q/16891019/15168). Granted, `puts()` is not `printf()`, but it is also not one of the functions that can be called safely in a signal handler. – Jonathan Leffler Dec 03 '22 at 05:44
  • You do some, but not all, of the setup work needed to use `sigaction()`, but then don't use it. That's not particularly sensible — and certainly isn't minimal. – Jonathan Leffler Dec 03 '22 at 05:47

1 Answers1

0

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
Allan Wind
  • 23,068
  • 5
  • 28
  • 38