Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for child process without using wait()

When using fork(), is it possible to ensure that the child process executes before the parent without using wait() in the parent?


This is related to a homework problem in the Process API chapter of Operating Systems: Three Easy Pieces, a free online operating systems book.

The problem says:

  1. Write another program using fork(). The child process should print "hello"; the parent process should print "goodbye". You should try to ensure that the child process always prints first; can you do this without calling wait() in the parent?

Here's my solution using wait():

#include <stdio.h>
#include <stdlib.h> // exit
#include <sys/wait.h> // wait
#include <unistd.h> // fork

int main(void) {
    int f = fork();
    if (f < 0) { // fork failed
        fprintf(stderr, "fork failed\n");
        exit(1);
    } else if (f == 0) { // child
        printf("hello\n");
    } else { // parent
        wait(NULL);
        printf("goodbye\n");
    }
}

After thinking about it, I decided the answer to the last question was "no, you can't", but then a later question seems to imply that you can:

  1. Now write a program that uses wait() to wait for the child process to finish in the parent. What does wait() return? What happens if you use wait() in the child?

Am I interpreting the second question wrong? If not, how do you do what the first question asks? How can I make the child print first without using wait() in the parent?

like image 322
stephenwade Avatar asked Jan 03 '23 13:01

stephenwade


2 Answers

I hope this answer is not too late.

Minutes ago, I have emailed Remiz(this book's author), and got such a replay(extract some segments):

Without calling wait() is hard, and not really the main point. What you did -- learning about signals on your own -- is a good sign, showing you will seek out deeper knowledge. Good for you!

Later, you'll be able to use a shared memory segment, and either condition variables or semaphores, to solve this problem.

like image 142
Chen Li Avatar answered Jan 12 '23 11:01

Chen Li


I can't see why second question would imply that answer is "yes" to the first.

Yes there is plenty of solutions to obtain what asked, but of course I suspect that all are not in the "spirit" of the problem/question where the focus in on fork/wait primitives. The point is always to remember that you can't assume anything after a fork regarding the way processes ran relatively to each other.

To ensure the child process print first you need a kind of synchronization in between both processes, and there is a lot of system primitives that have a semantic of "communication" between processes (for example locks, semaphores, signals, etc). I doubt one of these is to be used her, as they are generally introduced slightly later in such a course.

Any other attempt only that will only rely on time assumption (like using sleep or loops to "slow" down the parent, etc) can lead to failure, means that you will not be able to prove that it will always succeed. Even if testing would probably show you that it seems correct, most of the runs you would try will not have the bad characteristics that lead to failure. Remember that except in realtime OSes, scheduling is almost an approximation of fair concurrency.

NOTE:

As Jonathan Leffler commented, I also suppose that using other wait-like primitives is forbidden (aka wait4, waitpid, etc) -- "spirit" argument.

like image 34
Jean-Baptiste Yunès Avatar answered Jan 12 '23 10:01

Jean-Baptiste Yunès