2011-04-03 10 views
2
void childSignalHandler(int signo) { 
    int status; 

    pid_t pid = wait(&status); 

    struct PIDList* record = getRecordForPID(childlist, pid); 
    if (record != NULL) 
     record->returnValue = status; 
} 

快速的問題:處理SIGCHLD,因爲他們死如何記錄兒童的返回值

我希望此處理,當一個孩子去世(這個程序會生成大量的兒童),得到他們的返回值並記錄下來(最後三行)。這是否會做到這一點,還是我讓所有這些API業務都錯了?

謝謝你的時間!

(也,linux的API術語是令人毛骨悚然的地獄,檢查死亡兒童和諸如此類的東西)

回答

4

這應該做的工作,如果你設置你的函數爲SIGCHLD的處理程序。

但是,SIGCHLD可以發送到父進程不僅孩子退出後。其他一些事件也是以這種方式發出信號(例如,當孩子停止時)。有關詳細說明,請參見man wait(3)

+0

謝謝,隊友。 ':'' – 2011-04-03 17:07:09

4

注意信號不排隊。如果兩個孩子快速連續死亡,您只能接收一個SIGCHLD。所以,你應該實際上循環呼叫waitpid(),直到沒有更多的現有處理:

int status; 
pid_t pid; 

while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 
    if (WIFEXITED(status)) { 
     struct PIDList *record = getRecordForPID(childlist, pid); 

     if (record != NULL) 
      record->returnValue = WEXITSTATUS(status); 
    } 
} 
+2

請注意,在現代系統中,'SIGCHLD'排隊,但問題中的代碼仍然是錯誤的,因爲不能保證'wait()'將返回當前'SIGCHLD'實例的pid 。當wait()或類似函數報告子進程的狀態時,相應的'SIGCHLD'信號(如果有的話)被認爲是被接受的,並且信號處理程序不會被調用。 – jilles 2011-04-22 00:08:35

+0

@jilles我也觀察到這種行爲:''相應的SIGCHLD信號,如果有的話,被認爲是被接受的,信號處理程序不會被稱爲「'(快樂的調試時間...)。因爲我不確定我的應用程序是否正常運行,所以我很高興現在能夠對此發表評論。我仍在尋找官方參考。 – 2013-02-06 09:28:42

+0

@jilles這就是它,不是嗎? '如果定義了_POSIX_REALTIME_SIGNALS,並且實現對SIGCHLD信號進行排隊,那麼如果由於子進程的狀態可用而返回wait()或waitpid(),則任何與子進程的進程ID關聯的未決SIGCHLD信號都將被丟棄'從http://linux.die.net/man/3/waitpid – 2013-02-06 09:45:12