我正在为作业复制shell管道。我让管道全部工作(并且之后没有更改管道代码,因此已知可以工作),但是在管道的某个步骤中执行失败的情况下仍然需要终止管道。在实现该代码的某个时刻,管道开始出现意外行为。
长度为2的管道正常工作。 长度大于2的管道以下列方式失败:
以下是使用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
答案 0 :(得分:1)
要通过exit()
返回的值的处理提取传递给waitpid()
的状态,请使用宏WEXITSTATUS()
。
waitpid()
失败的测试也是错误的。 waitpid() return -1 on failure and in this case set
的errno , which then would make sense to be interpreted by a call to
PERROR()`。
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
}
}
}
...
答案 1 :(得分:0)
向所有试图找到waitpid问题的人致歉,因为它们只是表面错误。我的管道代码中的实际错误确实存在,我显然在此过程中失败了。