Search code examples
cunixsignals

Signals Behavior in C/C++ - Linux


Completely new to processes and signals and I was messing around with the following code I wrote :

void childSignalHandler(int signalCode) {

    if (signalCode == SIGUSR1)
        cout << "Child here : Received ping, responding" << endl;
}

void parentSignalHandler(int signalCode) {

    if (signalCode == SIGINT)
        cout << "Parent here : Pinging Child" << endl;

    else if (signalCode == SIGUSR1)
        cout << "Parent here : Received response" << endl;

}


int main() {

    int pid = fork();

    /* Child process*/
    if (pid == 0) {

        if (signal(SIGUSR1, childSignalHandler) == SIG_ERR) {
            perror("Child SIGUSR1");
            exit(1);
        }
        // This did the trick!
        if (signal(SIGINT,SIG_IGN) == SIG_ERR){
            perror("Child SIGINT");
            exit(1);
        }

        pause();
        kill(getppid(), SIGUSR1);
    } else {

        if (signal(SIGINT, parentSignalHandler) == SIG_ERR) {
            perror("Parent SIGINT");
            exit(1);
        }
        if (signal(SIGUSR1, parentSignalHandler) == SIG_ERR) {
            perror("Parent SIGUSR1");
            exit(1);
        }
        raise(SIGINT); // Maybe change it to pause(); to use keyboard instead ?
        kill(pid, SIGUSR1);
        pause();
    }


    return 0;
} 

The code above works perfectly fine and the expected behavior is :

Parent here : Pinging Child
Child here : Received ping, responding
Parent here : Received response

However when I tried the same thing using the keyboard Ctrl + C signal and changed the raise(SIGINT); to pause(); then the output was :

^CParent here : Pinging Child
^CParent here : Pinging Child

The way I thought this would work is :

  • Both processes will be paused
  • CTRL + C aka SIGINT will be sent to the parent process which will be unpaused
  • parentSignalHandler() will handle SIGINT and the appropriate message will be printed
  • Parent process will send a SIGUSR1 to the child process which will be unpaused and the parent process itself will be paused again
  • childSignalHandler() will handle SIGUSR1
  • Finally the child process will send a SIGUSR1 to the parent process,which once again will be handled by parentSignalHandler()

As it seems it does not work the way I imagined and any insight would be really helpful.

Edit -- Updated Code


Solution

  • raise(SIGINT) sends SIGINT signal only to the calling process - which is the parent process in this case. On the other hand, when you send the SIGINT signal using CTRL + C you send it to all of the foreground processes, i.e. the child process also receives it and therefore terminates. So there's no more a child process to reply to the SIGUSR1 signal of the parent process. Try ignoring the signal in the child process.