I'm working on replicating shell pipes for an assignment. I had the pipeline all working (and have not since changed the pipeline code, so that is known to work), but still needed to terminate the pipeline in the event of an execution failure in some step of the pipeline. At some point while implementing that code, the pipeline started exhibiting unexpected behavior.
Pipelines of length two work correctly. Pipelines of length greater than two fail in the following way:
- The first command in the pipeline executes
- Immediately afterwards — often before the first command finishes executing — the final command in the pipeline terminates
- The second command will then hang, apparently having received no input from the first command.
Here is the section code that uses waitpid (sans debug code):
for (int i = 0 ; i < num_cmds ; i++) {
if (waitpid(cmd_pids[i], &cmd_status[i], NULL) != cmd_pids[i]) {
printf("Error waiting for command %s\n", cmds[i]);
perror("Error");
}
if ((cmd_status[i] > 0) && (cmd_status[i-1] == 0)) {
killPipeline(SIGINT); //Kill pipeline; something failed
}
fflush(logfp);
}
Now here's the crux of why I think the waitpid section is to blame: due to some odd control flow that the assignment demands, I have found it convenient to initialize the values of cmd_status to -2. The logging function prints the return statuses of the child processes to a log, and the file says the exit status of the second function is -2, which is of course means that it isn't setting the exist status on the program. It seems that the pipeline isn't waiting for these programs to execute at all.
i.e.
input "ls | grep pipe | wc"
output:
You entered : list of pipe commands ls | grep pipe | wc
Creating process ls
Creating process grep pipe
Creating process wc
Waiting for command ls
0 0 0 //wc received no input, but somehow an EOF
Command ls finished
Waiting for command grep
^C //Terminate grep because it's waiting for input from a terminated process
Error waiting for command grep
Error: Interrupted system call
Command grep finished
Waiting for command wc
Command wc finished