Search code examples
cpidqnx

C Signal Handler professor example explanation


My QNX class notes has this example, I cant seem to figure out how my prof came up with that output. Can anyone explain this to me thoroughly?

When this program runs the parent process has a PID of 1234 and the child process has 5678.

Output 5678: counter = 0 1234: counter = 10

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>

/*
 * getpid() - returns the current processes pid.
 * getppid() - returns the parent processes pid.
 */

int counter = 0;

void signal_handler(int signo)
{
    counter++;
}

int main(int argc, char *argv[]) {
    int i = 0;
    int rv;

    struct sigaction sa;

    sa.sa_handler = signal_handler;
    //queue signals.
    sa.sa_flags = SA_SIGINFO;
    sigemptyset(&sa.sa_mask);

    sigaction(SIGUSR1, &sa, NULL);

    switch(fork())
    {
        case 0:
            for(i = 0; i < 10; i++)
            {
                kill(getppid(), SIGUSR1);
            }
            break;
        default:
            wait(&rv);
            break;
    }

    printf("%d: counter = %d\n", getpid(), counter);
    return 0;
}

Solution

  • The fork creates a child process with its own copy of counter.

    The kill, called by the child process, is sending a SIGUSR1 to the parent process because it is using getppid() to get the pid.

    The parent process is either blocked in the wait, or somewhere between the fork and the wait. For each SIGUSR1 sent by the child, the parent will jump into the signal handler, increment its copy of counter, and return to whatever it was doing.

    In general, wait can return with an EINTR error if a signal is handled while it is waiting. Setting SA_RESTART in sa.sa_flags ensures that system call will be restarted, but here it assumes that the wait will not be interrupted by the signal (does QNX guarantee this?).

    The child's copy of counter is not affected. The wait causes the parent to block until the child has exited. The child thus prints its value of counter, which is 0, and exits, the parent wakes from the wait and prints its value of counter, which is 10.