Search code examples
cprocessforkwaitpause

Wait for sibling process in C


While I was playing with C, and trying to learn more about processes, forks and wait, I've reached a problem where I'm not able to wait for a sibling process to finish until I can continue.

So, here's the problem:

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


int processoDisplayLyric;
int processoDisplayGraph;
int processoTimer;

int main(){

    int numeroMusicaAtual = 0;
    int continueWorking = 0;
    int fathersPID = getpid();


    while(continueWorking == 0) {


        //Create graph process
        processoDisplayGraph = fork();

        if(processoDisplayGraph == 0){
            int work = 0;
            while(work == 0){
                pause();
            }
        }

        if(processoDisplayGraph != 0){

            //Create lyric process.
            processoDisplayLyric =  fork();

            if(processoDisplayLyric == 0){

                int work = 0;
                while(work == 0){
                    pause();
                }
            }

        }

        if(processoDisplayLyric != 0 && processoDisplayGraph != 0){

            //Create timer process.
            processoTimer = fork();

            if(processoTimer == 0){
                printf("I was created and i just want to wait for my brothers.\n");
            }

        }

        if(getpid() != fathersPID){

            wait(processoDisplayLyric);
            wait(processoDisplayGraph);
        }else{
            //It's the father.
            int child_status;
            for (int i = 0; i < 2; i++) {
                pid_t wpid = waitpid(processoDisplayLyric, &child_status, 0);
                if (WIFEXITED(child_status))
                    printf("Saw %d done with %d\n", wpid, WEXITSTATUS(child_status));
                else
                    printf("Child %d terminated abnormally\n", wpid);
            }
        }

        numeroMusicaAtual++;
    }

}

The thing is: processDisplayLyric, processDisplayGraph and processTimer are created, BUT, the Timer DOESN'T wait for the other two to finish (something that should never happen!!!).


Solution

  • Under standard POSIX, only a parent process can wait for its (immediate) children to die.

    • Sibling processes cannot wait for other sibling processes to die.

    • Child processes cannot wait for parent processes to die.

    • A grandparent process cannot wait for grandchildren to die.

    There are ways to detect whether a parent process is dead (the result of getppid() is 1, or if you recorded the original PPID, then signalling it fails). You can find out if you could signal a known PID — and if it doesn't exist, you can't. There may be some alternatives on some platforms using other APIs. But there's no general analogy to wait() for siblings or parents (or any other related process) — only children can be waited for.

    Note that recent versions of Linux (since kernel 3.4) have the prctl() system call. The PR_SET_CHILD_SUBREAPER option allows a process other than the system process (PID 1 usually) to collect the status information of dead children in its process hierarchy. That's still not collecting sibling processes; it is only able to collect children, grandchildren, great-grandchildren, and so on.