我正在为一项任务复制贝壳管道。我让管道全部正常工作(从那以后还没有更改管道代码,所以这是已知的),但是在管道的某个步骤出现执行失败时,仍然需要终止管道。在实现该代码时,管道开始显示出意想不到的行为。
长度为2的管道工作正常。长度大于两条的管道以下列方式失效:
下面是使用waitpid的部分代码(sans调试代码):
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管道\ 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发布于 2013-05-13 16:07:03
要提取通过进程传递给exit()的状态,waitpid()返回的值使用宏WEXITSTATUS()。
此外,对waitpid()失败的测试也是错误的。waitpid() return -1 on failure and in this case seterrno, which then would make sense to be interpreted by a call toperror()`。
perror()读取errno的值。因此,只有在已知已设置perror()的情况下,调用errno才有意义。我在修改代码时删除了对perror("Error")的调用,但情况并非如此,如下所示。
for (int i = 0 ; i < num_cmds ; i++)
{
int status = -1;
int result = waitpid(cmd_pids[i], &status, NULL);
if (-1 == result)
{
perror("waitpid()"); /* added call to perror() here as errno is know to have been set */
}
else
{
if (result != cmd_pids[i])
{
fprintf(stderr, "Error waiting for command '%s'\n", cmds[i]);
/* removed call to perror() here as errno had not been set here. As this however should
log an error, I modded the code to printf to stderr, but stdout. */
}
else
{
cmd_status[i] = WEXITSTATUS(status);
if ((cmd_status[i] > 0) && ((0 == i) || (cmd_status[i-1] == 0))) /* This mod keeps
the app from dereferencing cmd_status in case i == 0, as this would lead to
cmd_status[-1], which is undefined beaviour. */
{
killPipeline(SIGINT); //Kill pipeline; something failed
}
}
}
...发布于 2013-05-13 17:43:24
向那些试图找出与waitpid有关的任何问题的人道歉,因为它们只是表面上的错误。实际的错误确实存在于我的管道代码中,这显然是我沿途被破坏的。
https://stackoverflow.com/questions/16526421
复制相似问题