簡體   English   中英

waitpid(pid,status,options)並不總是設置狀態

[英]waitpid(pid, status, options) not always setting status

我正在為任務復制外殼管道。 我使管道全部正常工作(此后沒有更改管道代碼,因此可以正常工作),但是在管道的某些步驟中執行失敗時,仍然需要終止管道。 在實現該代碼的某個時刻,管道開始表現出意外的行為。

長度為2的管道正常工作。 長度大於2的管道以下列方式失敗:

  1. 管道中的第一個命令執行
  2. 之后,通常在第一個命令執行完畢之前,管道中的最后一條命令終止
  3. 然后,第二條命令將掛起,顯然沒有收到第一條命令的輸入。

這是使用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管道| 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

要提取通過進程通過waitpid()返回的值傳遞給exit()的狀態,請使用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() , which then would make sense to be interpreted by a call to

perror()讀取errno的值。 因此,僅在已知已設置errno情況下,調用perror()才有意義。 如下所示,在我對代碼的修改中刪除的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
      }
    }
  }
  ...

向所有試圖通過waitpid查找任何問題的人致歉,因為它們只是表面上的錯誤。 實際的錯誤確實在我的管道代碼中,這顯然使我一路崩潰。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM