C waitpid(pid、状态、选项)不总是设置状态

C waitpid(pid、状态、选项)不总是设置状态,c,system-calls,waitpid,C,System Calls,Waitpid,我正在为一项任务复制shell管道。我让管道全部正常工作(此后没有更改管道代码,因此这是已知的正常工作),但仍然需要在管道的某个步骤执行失败时终止管道。在实现该代码的某个时刻,管道开始表现出意外的行为 长度为2的管道工作正常。 长度大于两条的管道以以下方式失效: 执行管道中的第一个命令 紧接着-通常在第一个命令完成执行之前-管道中的最后一个命令终止 第二个命令将挂起,显然没有收到第一个命令的输入 以下是使用waitpid(sans调试代码)的部分代码: 要从waitpid()返回的值提取通过进程

我正在为一项任务复制shell管道。我让管道全部正常工作(此后没有更改管道代码,因此这是已知的正常工作),但仍然需要在管道的某个步骤执行失败时终止管道。在实现该代码的某个时刻,管道开始表现出意外的行为

长度为2的管道工作正常。 长度大于两条的管道以以下方式失效:

  • 执行管道中的第一个命令
  • 紧接着-通常在第一个命令完成执行之前-管道中的最后一个命令终止
  • 第二个命令将挂起,显然没有收到第一个命令的输入
  • 以下是使用waitpid(sans调试代码)的部分代码:


    要从
    waitpid()
    返回的值提取通过进程传递给
    exit()
    的状态,请使用宏
    WEXITSTATUS()

    此外,
    waitpid()
    的故障测试也是错误的
    waitpid()失败时返回-1,在本例中设置为
    errno
    ,然后通过调用
    perror()来解释它

    perror()
    读取
    errno
    的值。因此,只有当已知已设置了
    errno
    时,调用
    peror()
    才有意义。调用
    perror(“Error”)
    I remove in my modification of your code时,情况并非如此,如下所示

    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
          }
        }
      }
      ...
    
    for(int i=0;i0)和((0==i)| |(cmd_状态[i-1]==0))/*此模块保持
    在i==0的情况下,应用程序不会取消对cmd_状态的引用,因为这将导致
    cmd_状态[-1],它是未定义的beaviour*/
    {
    killPipeline(SIGINT);//Kill pipeline;某些操作失败
    }
    }
    }
    ...
    
    向所有试图发现waitpid问题的人致歉,因为这些问题只是表面错误。实际错误确实存在于我的管道代码中,我显然在过程中破坏了管道代码。

    我认为在您的第二个if语句中,cmd_status[I-1]!=0,因为0表示这些进程尚未完成(更改状态).虽然我看到这里有很多小问题,我很感激你指出了这些问题,但这些变化都没有(我已经实施了)实际上解决了这个奇怪的行为。实际上,我试图从上一次提交开始,并重新实现管道更改以重新启动。同样的行为,因此我无法再保证管道代码是正确的。
    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
    
    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
          }
        }
      }
      ...