簡體   English   中英

在兒童中使用execl的waitpid與ECHILD返回-1嗎?

[英]waitpid with execl used in child returns -1 with ECHILD?

如果我正在使用execl,何時需要使用waitpid是子進程,可能需要一些時間才能完成?

當我在父級中使用waitpid時,它使我的孩子正在運行,因為waitpid的返回值是0。一段時間后,我試圖在另一個函數中使用waitpid,在該函數中我將ECHILD返回-1。 如果不確定天氣孩子是否完成,應該何時使用waitpid?

//pid_t Checksum_pid = fork();
Checksum_pid = fork();

if (Checksum_pid == 0)
{
    execl(path, name, argument as needed, ,NULL);
    exit(EXIT_SUCCESS);     
}
else if (Checksum_pid > 0)
{ 
    pid_t returnValue = waitpid(Checksum_pid, &childStatus, WNOHANG);

    if ( returnValue > 0)
    {
        if (WIFEXITED(childStatus))
        {
            printf("Exit Code: _ WEXITSTATUS(childStatus)") ;               
        }
    }
    else if ( returnValue == 0)
    {
        //Send positive response with routine status running (0x03)
        printf("Child process still running") ; 
    }
    else
    {
        if ( errno == ECHILD )
        {
             printf(" Error ECHILD!!") ;
        } 
        else if ( errno == EINTR )
        {
            // other real errors handled here.
            printf(" Error EINTR!!") ;
        }
        else
        {
            printf("Error EINVAL!!") ;
        }       
    }
}
else
{   
    /* Fork failed. */
    printf("Fork Failed") ;
}

如果信號SIGCHLD被忽略(這是默認設置),並且您跳過了Jonathan提到的WNOHANG,waitpid將掛起,直到子項退出,然后代碼ECHILD失敗。 我本人是在父進程僅應等待子進程完成的情況下遇到此問題的,而為SIGCHLD注冊處理程序似乎有點過頭了。 自然的后續問題是“在這種情況下是否可以將ECHILD視為預期事件,還是我總是應該為SIGCHLD編寫處理程序?”,但對此我沒有答案。

waitpid(2)文檔中

成就

(用於waitpid()或waitid())由pid(waitpid())或idtype和id(waitid())指定的進程不存在或不是調用進程的子進程。 (如果將SIGCHLD的操作設置為SIG_IGN,這可能會發生在自己的孩子身上。另請參見關於線程的Linux Notes部分。)

再往下走

POSIX.1-2001指定如果將SIGCHLD的處置設置為SIG_IGN或為SIGCHLD設置SA_NOCLDWAIT標志(請參見sigaction(2)),則終止的子代不會成為僵屍,並且對wait()或waitpid( )將阻塞,直到所有子級都終止,然后在errno設置為ECHILD時失敗。 (原始POSIX標准未指定將SIGCHLD設置為SIG_IGN的行為。請注意,即使SIGCHLD的默認設置為“ ignore”,將設置顯式設置為SIG_IGN也會導致對僵屍進程子進程的不同處理。)Linux 2.6符合此要求。規格。 但是,Linux 2.4(及更早版本)沒有:如果在忽略SIGCHLD的同時進行了wait()或waitpid()調用,則該調用的行為就像未忽略SIGCHLD一樣,也就是說,該調用將阻塞直到下一個子進程終止,然后返回該子進程的進程ID和狀態。

另請參閱此答案

如果您等待WNOHANG ,那么除非您的孩子已經死亡,否則您將不會獲得任何有用的狀態-甚至可能還沒有去世(當父級執行該操作時,它可能仍在等待從磁盤加載可執行文件)。 waitpid() )。

如果您想知道孩子已經完成,請不要使用WNOHANG -在第三個參數中使用0 ,除非您想了解未跟蹤或繼續的進程。 這將一直等待,直到由Checksum_pid標識的進程退出,或者系統以某種神秘的方式失去了對它的跟蹤(我從未見過這種情況)。


此代碼產生Exit Code: 0作為輸出:

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

int main(void)
{
    pid_t Checksum_pid = fork();

    if (Checksum_pid < 0)
        printf("Fork Failed\n");
    else if (Checksum_pid == 0)
    {
        execl("/bin/sleep", "/bin/sleep", "2", NULL);
        exit(EXIT_FAILURE);
    }
    else
    {
        int childStatus;
        pid_t returnValue = waitpid(Checksum_pid, &childStatus, 0);

        if (returnValue > 0)
        {
            if (WIFEXITED(childStatus))
                printf("Exit Code: %d\n", WEXITSTATUS(childStatus));
            else
                printf("Exit Status: 0x%.4X\n", childStatus);
        }
        else if (returnValue == 0)
            printf("Child process still running\n");
        else
        {
            if (errno == ECHILD)
                printf(" Error ECHILD!!\n");
            else if (errno == EINTR)
                printf(" Error EINTR!!\n");
            else
                printf("Error EINVAL!!\n");
        }
    }

    return 0;
}

它與您的代碼非常相似; 我只是將對fork()的檢查移到了頂部。 我仍然希望擺脫if語句的“繁忙樹”,但這並不重要。 運行此代碼會怎樣? 為了得到ECHILD錯誤,您必須更改什么(可以更改它以便得到ECHILD錯誤)嗎?

當您設法從中獲得代碼來重現該問題時,我們可以弄清楚為什么您會得到這種行為。

在帶有GCC 4.8.2的Mac OS X 10.9.2 Mavericks和帶有GCC 4.8.1的Ubuntu 13.10上進行了測試(我需要添加-D_XOPEN_SOURCE=700以使其能夠使用嚴格的編譯標志進行編譯; Mac OS X無需使用它即可進行編譯),但我不希望在其他地方得到不同的結果。

int start(int Area)
{

        int childStatus;
        pid_t Checksum_pid = fork();

        if(Checksum_pid < 0)
        {   
            /* Fork failed. */
            printf(" Fork Failed") ;

        }   
        else if (Checksum_pid == 0)         
        {

            for (int i = 0; i<5; i++)

            {

                if ( g_area[i] == Area)
                {

                    execl(ScriptPath, ScriptName, NULL);

                }
            }

            exit(EXIT_FAILURE);

        }

        else        
        { 
            /* This is the parent process. */           
            pid_t returnValue = waitpid(Checksum_pid, &childStatus, 0);


            if ( returnValue > 0)
            {
                // Check if child ended normally 
                printf("WAITPID Successful") ;                  

                if (WIFEXITED(childStatus))
                {
            printf("Exit Code: _ WEXITSTATUS(childStatus)");
                }

            }

            else if ( returnValue == 0)
            {

                printf("Child process still running") ;

            }
            else
            {

                if ( errno == ECHILD )
                {
                     printf("Error ECHILD!!") ;
                } 
                else if ( errno == EINTR )
                {
                    printf("Error EINTR!!") ;
                }
                else
                {
                    printf(" Error EINVAL!!") ;
                }       
                retCode = FAILED;
            }        

        }            
}

暫無
暫無

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

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