【发布时间】:2013-05-13 16:03:18
【问题描述】:
我正在为一项任务复制外壳管道。我让管道全部工作(并且没有更改管道代码,因此已知它可以工作),但仍然需要在管道的某个步骤中发生执行失败的情况下终止管道。在实现该代码的某个时刻,管道开始出现意外行为。
长度为 2 的管道可以正常工作。 长度大于 2 的管道会以下列方式失败:
- 管道中的第一个命令执行
- 紧接着 - 通常在第一个命令完成执行之前 - 管道中的 final 命令终止
- 然后第二个命令将挂起,显然没有收到来自第一个命令的输入。
这是使用waitpid的部分代码(无调试代码):
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);
}
现在这就是为什么我认为 waitpid 部分应该受到指责的症结所在:由于分配需要一些奇怪的控制流,我发现将 cmd_status 的值初始化为 -2 很方便。日志功能将子进程的返回状态打印到日志中,文件说第二个函数的退出状态为-2,这当然意味着它没有设置程序的存在状态。管道似乎根本没有等待这些程序执行。
即
输入“ls | grep pipe | wc”
输出:
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
【问题讨论】:
-
我认为在您的第二个 if 语句中, cmd_status[i-1] != 0 因为 0 表示这些进程尚未完成(更改状态)。
标签: c system-calls waitpid