2017-08-16 7 views
0

これをgdbで実行すると、親がwaitpidでハングしてしまい、その理由がわかりません。親はargvから引数をとり、パイプ経由で子に送信することになっています。それから、親は子からの引数の合計を返すことになっています。なぜこれをやっているのか分かりません。親プロセスはwaitpidを呼び出した後にハングします

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <sys/poll.h> 

static int myPipe[2]; 

int main(int argc, char **argv) 
{ 
    pid_t pid; 
    int value; 
    int status; 
    // set up pipe 

    if(pipe(myPipe)) 
    { 
     printf("pipe error\n"); 
     return -1; 
    } 

    // call fork() 
    printf("CS201 - Assignment 3 Premium - I. Forgot\n"); 
    pid = fork(); 
    if (pid == 0) { 
     // -- running in child process -- 
     int  sum = 0; 
     close(myPipe[1]); 

     for(int i = argc; i > 1; i--) 
     { 
      read(myPipe[0], &value, sizeof(value)); 
      sum += value; 
     } 

     // Return sum of numbers. 
     return sum; 
     } 
    else { 
     // -- running in parent process -- 
     int sum = 0; 
     close(myPipe[0]); 

for(int i = argc; i > 1; i--) 
     { 
      value = atoi(argv[i-1]); 
      write(myPipe[0], &value, sizeof(value)); 
     } 
     waitpid(pid, &status, 0); 
     sum = status; 

     printf("sum = %d\n", sum); 
     return 0; 
     } 

答えて

1

あなたの問題は親に、そしてあなた慎重myPipe[0]近い、と不思議に代わりmyPipe[1]まだオープンのそれへの書き込みを決めるということです。あなたがシステムコールをエラーチェックした場合、あなたは子供にデータを送信できなかったことを知っています。そのままでは、子はまだデータが到着するのを待っていて終了せず、親は終了するために終了しない子を待っているので、デッドロックが発生します。

私はstderr.cstderr.hから関数をエラー報告を使用しています - エラー(および進捗状況を)報告するGitHubの(https://github.com/jleffler/soq/tree/master/src/libsoq)から提供されているコードを。

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include "stderr.h" 

static int myPipe[2]; 

int main(int argc, char **argv) 
{ 
    pid_t pid; 
    int value; 
    int status; 
    err_setarg0(argv[0]); 
    err_setlogopts(ERR_PID|ERR_MICRO); 

    if (pipe(myPipe) != 0) 
     err_syserr("pipe failed: "); 

    // call fork() 
    printf("CS201 - Assignment 3 Premium - I. Forgot\n"); 
    pid = fork(); 
    if (pid < 0) 
     err_syserr("fork failed: "); 
    else if (pid == 0) 
    { 
     // -- running in child process -- 
     int sum = 0; 
     if (close(myPipe[1]) != 0) 
      err_syserr("failed to close write end of pipe in child: "); 

     for (int i = argc; i > 1; i--) 
     { 
      if (read(myPipe[0], &value, sizeof(value)) != sizeof(value)) 
       err_syserr("failed to read from parent: "); 
      sum += value; 
     } 
     if (close(myPipe[0]) != 0) 
      err_syserr("failed to close read end of pipe in child: "); 

     err_remark("Exiting: sum = %d\n", sum); 
     return sum; 
    } 
    else 
    { 
     // -- running in parent process -- 
     int sum = 0; 
     close(myPipe[0]); 

     for (int i = argc; i > 1; i--) 
     { 
      value = atoi(argv[i - 1]); 
      err_remark("Writing: %d\n", value); 
      if (write(myPipe[1], &value, sizeof(value)) != sizeof(value)) 
       err_syserr("failed to write to child: "); 
     } 
     if (waitpid(pid, &status, 0) != pid) 
      err_syserr("failed to wait for child %d: ", pid); 
     sum = status; 

     printf("sum = %d\n", sum); 
     if (WIFEXITED(status)) 
      printf("exit status: %d\n", WEXITSTATUS(status)); 
     return 0; 
    } 
} 

および実施例の出力(fp71.cソースコード、プログラムfp71):

$ gcc -O3 -g -I./inc -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \ 
>  -Wstrict-prototypes fp71.c -o fp71 -L./lib -lsoq 
$ fp71 1 2 4 7 
CS201 - Assignment 3 Premium - I. Forgot 
fp71: 2017-08-15 20:11:48.453688 - pid=86097: Writing: 7 
fp71: 2017-08-15 20:11:48.454267 - pid=86097: Writing: 4 
fp71: 2017-08-15 20:11:48.454275 - pid=86097: Writing: 2 
fp71: 2017-08-15 20:11:48.454281 - pid=86097: Writing: 1 
fp71: 2017-08-15 20:11:48.454348 - pid=86098: Exiting: sum = 14 
sum = 3584 
exit status: 14 
$ 

進値3584は0x0E00を16進数に対応します。もしあなたがWIFEXITED()WEXITSTATUSでそれを鎮めるならば、それは14に相当します。 (Exit values bigger than 255 — possible?も参照してください)

関連する問題