Search code examples
c++ubuntuexecparent-childwaitpid

Why does this code fail? child not waiting


Ok so I have been trying to learn to master child processes and properly waiting for them to finish. I have read a lot of Stack Overflow Q/A and I still can't seem to get this to work as I want it to. I have been reading/searching through the book (C++ Primer plus 6th ed.) - I have done some research and still I can't make it wait as I wanted to.

So I have looked at several things here on Stack Overflow for reference: Checking the status of a child process in C++

Here is what I have tried so far:

using namespace std;
int main() {
int status;
pid_t child;
child = fork();

if ( child > 0 ) {
    cout << "\nChild #1 is in charge\n";
    execlp("ls", "ls", NULL);
}

else if ( child < 0 ) {
    cout << "\nSomething wen't wrong in the forking process\n";
}

else {

}

child = fork();
if ( child > 0 ) {
    cout << "\nSecond child is in charge\n";
    execlp("locate", "locate", "etc", NULL);
}

else if ( child < 0 ) {
    cout << "\nSomething went wrong in the forking of second child!\n";
}

else {

}

Now this would show Child #1 is in charge and Second child is in charge then it would mix the two commands (I see some ls in between locate etc).

Second thing I have tried:

using namespace std;
int main() {
int status;
pid_t child;
pid_t ch_status = waitpid(child, &status, WNOHANG);

child = fork();
if ( child > 0 ) {
    cout << "\nChild is in charge\n";
    execlp("ls", "ls", NULL);
}

else if ( child < 0 ) {
    cout << "\nSomething wen't wrong in the forking process\n";
}

if ( ch_status == 0 ) {

}

else if ( ch_status == -1 ) {
    cout << "\nERROR IN CHILD #1\n";
}

else {

}

child = fork();
if ( child == 0 ) {
    cout << "\nSecond child is in charge\n";
    execlp("locate", "locate", "etc", NULL);
}

else if ( child < 0 ) {
    cout << "\nSomething went wrong in the forking of second child!\n";
}

if ( ch_status == 0 ) {

}

else if ( ch_status == -1 ) {
    cout << "\nERROR IN CHILD #1\n";
}

else {

}

child = fork();
if ( child > 0 ) {
    cout << "\nThird child is in charge!\n";
    execlp("echo", "echo", "herro", NULL);
}

else if ( child < 0 ) {
    cout << "\nForking of third child failed!\n";
}

if ( ch_status == 0 ) {

}

else if ( ch_status == -1 ) {
    cout << "\nERROR IN CHILD #2\n";
}

else {

}

return 0;
}

This is more based on the link which I provided, it yielded the same result as the first test run I did, except it would also show ERROR IN CHILD #1/2.

The commands are irrelevant, I just wan't to understand what I am doing wrong here... I have also tried nesting them in else { //start second fork here }, but I got nowhere with this either.

From what I understand after reading the waitpid(2) manual I should be using WNOHANG; http://linux.die.net/man/2/waitpid

Any suggestions/pointers are greatly appreciated.

If possible, please submit a sample code of how you would accomplish the correct result (execute command 1 -> wait until done -> execute command 2 -> exit).

Look forward to replies.


Solution

  • You should be calling waitpid() in the parent after you fork. That is, it should go into the child > 0 branch.

    The function's purpose is to "wait for a change in the child state." However, you're calling it before you spawn a child.

    The code should then look like this:

    using namespace std;
    int main() {
    
    int status;
    pid_t child;
    
    child = fork();
    if ( child == 0 ) {
        cout << "\nChild is in charge" << endl;
        execlp("ls", "ls", NULL);
    } else if ( child < 0 ) {
        cout << "\nSomething wen't wrong in the forking process" << endl;
    } else {
        cout << "Parent waiting" << endl;
        pid_t ch_status = waitpid(child, &status, WNOHANG);
        if (ch_status == -1) {
          cout << "\nERROR IN CHILD #1" << endl;
        }
    }
    
    child = fork();
    //same procedure as above
    
    }