2015-05-26 48 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。 –