1

The following code is taken from practice problem 8.8 from CS:APP3e on page number 809

volatile long counter = 2;

void handler1(int sig) 
{
    sigset_t mask, prev_mask;

    Sigfillset(&mask);
    Sigprocmask(SIG_BLOCK, &mask, &prev_mask);  /* Block sigs */
    Sio_putl(--counter);
    Sigprocmask(SIG_SETMASK, &prev_mask, NULL); /* Restore sigs */

    _exit(0);
}

int main() 
{
    pid_t pid;
    sigset_t mask, prev_mask;

    printf("%ld", counter);
    fflush(stdout);

    signal(SIGUSR1, handler1);
    if ((pid = Fork()) == 0) {
        while(1) {};
    }
    Kill(pid, SIGUSR1); 
    Waitpid(-1, NULL, 0);

    Sigfillset(&mask);
    Sigprocmask(SIG_BLOCK, &mask, &prev_mask);  /* Block sigs */
    printf("%ld", ++counter);
    Sigprocmask(SIG_SETMASK, &prev_mask, NULL); /* Restore sigs */

    exit(0);
}

The task is to find the printed output of this program. According to the textbook, the answer should be "213". The explanation given is the following :

The parent starts by printing '2', then forks the child, which spins in an infinite loop. The parent then sends a signal to the child and waits for it to terminate. The child catches the signal (interrupting the infinite loop), decrements the counter (from an initial value of 2), prints '1', and then terminates. After the parent reaps the child, it increments the counter (from an initial value of 2), prints '3', and terminates.

I don't understand how the last call to printf takes the initial value of counter as 2. After the child catches the SIGUSR1 signal and passes control to handler1, it decrements the global variable to 1, and terminates because of the _exit(0) syscall. After the parent process reaps the terminated child process, the call printf("%ld", ++counter); should use the value of counter as 1 and print "2". Thus, the printed output should've been "212". Can anyone explain why "213" is printed instead ?

0 Answers0