2015-05-26 50 views
0

我已经看过关于这个的一些主题后的等待(),但未能解决这个问题 -憋屈fork()的

我分叉两次,但等待最后PROC当它卡住上等待() ,如果我删除的wait(),它移动,但显然它不会等待:

这里是有关的代码:

/*Fork #1*/ 
    if((pid=fork())==0) 
    { 
    if(command -> inputRedirect != NULL) 
    { 
     fclose(stdin); 
     fopen(command -> inputRedirect,"r"); 
    } 
    fclose(stdout); 
    dup(pipefd[1]); 
    close(pipefd[1]); 
    i=execvp(command->arguments[0],command->arguments); 
    } 
    if(i == -1) 
    { 
    perror("Error"); 
    return 1; 
    } 
    printf("\nParent: %d , Child: %d\n",getpid(),pid); 

    command = command->next; 
    /*Fork #2*/ 
    if((pid=fork())==0) 
    { 

    fclose(stdin); 
    dup(pipefd[0]); 
    close(pipefd[0]); 

    if(command -> outputRedirect != NULL) 
    { 
     fclose(stdout); 
     fopen(command ->outputRedirect,"w"); 
    } 

    i=execvp(command->arguments[0],command->arguments); 
    _exit(0); 
    } 

    if(i == -1) 
    { 
    perror("Error"); 
    return 1; 
    } 

    if(command->blocking == 1) 
    { 
    int test=0; 
    printf("\nParent: %d , Child: %d\n",getpid(),pid); 
    printf("\ntest1\n"); 
    while((test=wait(NULL)) != pid) 
    { 
     printf("\n %d \n ", test); 
    } 
    printf("\ntest2\n"); 
    } 
    return 0; 
} 

我加了一些测试,看看一些PID输出和最新内部运行,它等待第一个chil进程完成,并打印正确的ID,但第二个只是阻止。

但是我在屏幕上看到第二个过程完成(从过程输出)。

任何有关该主题的帮助将是最受欢迎的。

谢谢。

+1

听起来像第二个孩子不会退出。 –

+0

流程输出不一定是它是否退出的可靠指标。改为通过'ps'命令检查过程列表。 –

+0

不过,我不认为是这样,有两个原因 - 如果一个孩子退出,它仍然是一个“僵尸”,直到等待被调用,其次,如果没有孩子procsess调用wait()什么也不做,我有尝试不同的代码变化,不用一段时间,仍然阻止:/ –

回答

1

这是一个过程调用wait()当没有未收回的孩子(wait()将返回-1在这种情况下,设置errnoECHILD)错误,所以实际上wait()挂起表示有一个子进程尚未收集。一旦该子进程实际上已经终止 - 包括它在wait()调用之前已经终止 - 父进程就有资格进行调度,并且应该立即从wait()返回。因此wait()呼吁挂断你是一个很好的迹象表明,两个子进程中的一个实际上还没有退出。

正如我在评论中写的,孩子的输出不一定是它是否退出的可靠指示。当孩子退出时,它会变成僵尸,直到它被收集,并且你可以在流程表中检查它。

你的文件描述符处理看起来有点奇怪,这可能是你的问题的根源。首先,如果您想将管道FD复制到儿童标准流中,则应使用dup2()以明确指定,而不是使用close() + dup()。但是,更可能是您的实际问题的是父进程未能关闭其管道FD的副本。如果第二个孩子在其标准输入(来自管道)上等待EOF,则父母未能关闭其管道的写入结束副本将阻止孩子终止。

+0

谢谢!愚蠢的我,我一直在解决这个问题很长时间,却没有意识到我忘了关闭父母双方的FD。 –