2
votes

I'm a student and I am trying to understand signals within a course about Unix programming.

To start, I wanted to test a simple example: a process makes a child and needs a confirmation of the actual creation. I fork, and within the child I send a SIGUSR1 to the father with kill(getppid(), SIGUSR1); Then, within the father, I wrote a pause(); sys call to block the process until a signal is received, and then I wrote the (sigaction(SIGUSR1, &sa, NULL) check.

Problem is, the signal is sent and the program stops, with no handler execution.

I compile it with

$gcc -Wall -o test test.c

I get no warnings, and the output is

$I am the father
$I am the child
$User defined signal 1

I know I could do this in other ways (with sleep sys call, etc.), but I just want to understand why this code doesn't work.

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void new_child (int sig){
    write(1,"I made a new child\n",50);
}

int main(){
    pid_t child;
    struct sigaction sa;            
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sa.sa_handler = new_child;
    switch(child = fork()){
        case -1:
            printf("Error.\n");
            exit(EXIT_FAILURE);
        case 0:
            printf("I am the child\n");
            kill(getppid(), SIGUSR1);
            break;
        default:
            printf("I am the father\n");
            pause();
            if (sigaction(SIGUSR1, &sa, NULL) == -1){
                printf("Signal error.\n");
                exit(EXIT_FAILURE);
            }
            printf("I'm done.");
            kill (child, SIGKILL);
            exit(EXIT_SUCCESS);
    }
}

I know this question has already been asked, but I cannot seem to find a solution that works in my case.

1
You must change the signal at the beginning of the code so that it can execute as soon as SIGUSR is received - Anjaneyulu
Thank you very much. This actually worked! I found the sys call pause() to be very useful but my book didn't even have an example of its use. - Eli Nax 9
write(1,"I made a new child\n",50); will write a lot of junk to file descriptor 1 as the length of "I made a new child\n" is much less than 50. It's technically undefined behavior and can cause your program to fail. - Andrew Henle
@Anjaneyulu: "You must change the signal at the beginning of the code ..." this restriction is a bit tight. The signal handler needs to be install latest just before calling fork(). - alk
@alk yest the signal handler not the signal - Anjaneyulu

1 Answers

0
votes

You must change the signal at the beginning of the code so that it can execute as soon as SIGUSR is received – Anjaneyulu

"You must change the signal at the beginning of the code ..." this restriction is a bit tight. The signal handler needs to be install latest just before calling fork(). – alk