1

I'm attempting to simulate a shell processing foreground commands but I'm running into trouble when it comes to reaping child processes. I spawn multiple processes using fork in the following code.

while (currCmdListNode != list_end(&currentPipeline->commands)) { 

            if (fork() == 0) 
            {
                printf("Child created with pid %d \n", getpid());
                currentCmd = list_entry(currCmdListNode, struct esh_command, elem);
                execvp(currentCmd->argv[0], currentCmd->argv);
            }

            currCmdListNode = list_next(currCmdListNode);
        }

Then, I try to reap all these processes from the parent process using the following code.

        while((pid = waitpid(-1, &status, WUNTRACED)) > 0)
        {
           if (WIFEXITED(status))
           {
              printf("child %d terminated normally with exit status=%d\n", pid, WEXITSTATUS(status));
           }
           else 
           {
              printf("child %d terminated abnormally\n", pid);
           }
       }

Let's say I run this code so that two child processes spawn from my initial fork. My reap functionality will return saying it reaped the first child. However, it will hang once it hits waitpid the second time, and I will never get a message saying it reaped the second child. If I spawn four child processes, then maybe two will get reaped, then it will hang. What is going on here? Do I have to do some sort of blocking of the SIGCHLD signal? If so, where should I be blocking it?

RJ Stank
  • 31
  • 2
  • There might be a child that hasn't exited yet that `waitpid()` is waiting for. You should put some error code after the `execvp()`, just in case the command cannot be executed. Not putting something that (preferably) reports the failure to execute and exits can leave you with multiple processes at work when you really don't want them. – Jonathan Leffler Feb 14 '20 at 23:57
  • You might need to track the PIDs of the processes you create so you can wait for them to exit explicitly, rather than waiting for everything to finish. In due course, you'll probably have background jobs too (traditionally run with an `&` at the end of the pipeline). Then you don't want to wait for all commands to exit before continuing. – Jonathan Leffler Feb 14 '20 at 23:59
  • If you're messing with the SIGCHLD signal handling, it could easily be confusing things. Roughly — don't! If you're not fiddling with SIGCHLD, do you trust the libraries you are using not to fiddle with it? The standard C and POSIX libraries won't mess you up. – Jonathan Leffler Feb 15 '20 at 00:04
  • Are you sure all the children are exiting? Use `ps` to see what state the children are in. – Barmar Feb 15 '20 at 00:14
  • Thanks Jonathan and Barmar, it turns out that waitpid() was actually working correctly. After some error checking I realized the processes actually weren't exiting. Appreciate the help! – RJ Stank Feb 18 '20 at 15:00

0 Answers0