Home > Net >  How to use signals in C and How they react?
How to use signals in C and How they react?

Time:02-16

I am trying to learn all interactions about signals and I discovered a funny interaction in it I can't understand.

Here's an abstract of the program, Im instructed to do execvp with grandchild, while child needs to wait for grandchild to finish. It runs correctly when without any signal interactions.

void say_Hi(int num) { printf("Finished\n"); }

int main() {
    int i = 2;

    char *command1[] = {"sleep", "5", NULL};
    char *command2[] = {"sleep", "10", NULL};

    signal(SIGCHLD, SIG_IGN);
    signal(SIGUSR1, say_Hi);

    while(i > 0) {
        pid_t pid = fork();
        if (pid == 0) {
            pid_t pidChild = fork();
            if (pidChild == 0) {
                if (i == 2) {
                    execvp(command1[0], command1);
                } else {
                    execvp(command2[0], command2);
                }
            } else if (pidChild > 0) {
                waitpid(pidChild, 0, 0);
                // kill(pid, SIGUSR1);
                printf("pid finished: %d\n", pidChild);
                exit(EXIT_FAILURE);
            }
            exit(EXIT_FAILURE);
        } else {
            //parent immediately goes to next loop
            i--;
        }
    }
    cin >> i; //just for me to pause and observate answers above
    return 0;
}

As shown above, kill(pid, SIGUSR1); is commented, the program runs correctly.

Output:

pid finished: 638532 //after 5 sec
pid finished: 638533 //after 10 sec

However, when it is uncommented. Output becomes:

Finished
pid finished: 638610 //after 5 sec
Finished
Finished
Finished
Finished
pid finished: 638611 //after 5 sec too, why?
Finished

I would like to ask:

  • The whole program finished at once after 5 secs and a total of 6 "Finished" is printed out. Why is so?

  • Is there a way for me to modify it so that say_Hi function run in a total of two times only, in a correct time interval?


Please forgive me if my code looks stupid or bulky, I'm a newbie in programming. Any Comments about my code and help are appreciated!

CodePudding user response:

void say_Hi(int num) { printf("Finished\n"); }

printf cannot be called in a signal handler. None of the C or the C library functions (with few exceptions) can be called in the signal handler. You can't even allocate or delete any memory from a signal handler (using either the C or the C library), except by using low-level OS calls like brk() or sbrk(). This is because of a very simple reason: that none of the C or the C library functions are signal-safe (with very few exceptions). Only function calls that are explicitly designated as "signal-safe" can be called from a signal handler. None of the C or C library functions or classes (with few exceptions) are signal-safe. The End.

The only thing that can be called from a signal handler are low-level operating system calls, like read() and write(), that operate directly on file handles. They are, by definition, signal-safe.

For this simple reason the shown code, when it comes to signals, is undefined behavior. Trying to analyze or figure out your programs behavior, from that respect, such as why or why not you see this message, is completely pointless. It cannot be logically analyzed. This is undefined behavior.

CodePudding user response:

Answer:

kill(getpid(), SIG_USR1);
  • Related