2012-05-25 113 views
4

我有一個分叉到子進程的進程。如果父進程存在,子進程不應該存在。所以,我在子進程中調用:: prctl(PR_SET_PDEATHSIG,SIGKILL)來殺死父進程。最後發生的是父線程調用pthread_exit,並且該線程最終成爲殺死子進程的催化劑。在父線程退出時調用prctl(PR_SET_PDEATHSIG,SIGNAL),而不是父進程退出

這裏是我的代碼:

parent.cpp:

#include <sys/prctl.h> 
#include <signal.h> 
#include <unistd.h> 
#include <pthread.h> 
#include <iostream> 

void* run(void* ptr) { 

    std::cout << "thread:" << getpid() << ":" << std::hex << pthread_self() << ":" << std::dec << getppid() << std::endl; 
    auto pid = fork(); 
    if (pid != 0) { 
     sleep(1); 
    } 
    else { 
     char* arg = NULL; 
     execv("./child", &arg); 
    } 
    return NULL; 
} 

int main() { 

    std::cout << "main:" << getpid() << ":" << std::hex << pthread_self() << ":" << std::dec << getppid() << std::endl; 

    pthread_t threadid; 
    pthread_attr_t attr; 

    ::pthread_attr_init(&attr); 
    ::pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 
    ::pthread_create(&threadid,&attr,run,NULL); 

    sleep(6); 

    return 0; 
} 

child.cpp:

#include <sys/prctl.h> 
#include <signal.h> 
#include <unistd.h> 
#include <iostream> 

int main() { 
    std::cout << "child:" << getpid() << ":" << std::hex << pthread_self() << ":" << std::dec << getppid() << std::endl; 
    ::prctl(PR_SET_PDEATHSIG, SIGKILL); 
    sleep(6); 


    return 0; 
} 

運行在命令行中執行以下操作:

$ ./parent 

同時,運行下面的內容翼找到孩子的狀態:

$ for i in {1..10000}; do ps aux | grep child ; sleep .5; done 

孩子死了。如果你在孩子身上取出prctl電話,它不會失效。

http://www.kernel.org/doc/man-pages/online/pages/man2/prctl.2.html prctl頁面似乎描述此調用應在父進程死亡時,調用SIGKILL,而不是父線程。當父進程死亡而不是父線程時,有沒有辦法讓prctl殺死子進程?

回答

-1

您需要了解線程有兩件事情(我的知識是從C,但是這種實現似乎符合我用C做了大部分)

進程是一個大的,重的東西,可以包含多個線程,我相信你知道。

我相信這裏發生了什麼:父線程被終止,並且子線程永遠也不會收到它應該死的任何信號。

您需要確保您的流程何時結束,它將廣播它包含的所有線程,而不僅僅是父線程。

這表現以及由下圖從the LLNL tutorial on POSIX threads

enter image description here

我認爲解決方法是隻是爲了確保你調用在pthread_join當你初始化你的線程。

希望這會有所幫助!

+0

恐怕看起來問題並不在於線程過早死亡。我是故意這樣做的。因此,孩子睡6秒,而父母線只睡1秒。 我試圖做的一點是父進程睡6秒,而孩子也睡6秒。然而,孩子只有1(當分叉的線程死亡,但父進程仍在繼續時)失效。 有沒有什麼辦法可以讓prctl在父進程的時候死掉,而不是分叉死的線程? – user1418199

+0

我並不完全確定,但我很確定,當線程正在休眠時,它完全暫停。也就是說,沒有任何短於SEGFAULT類型的錯誤會導致它調用'pthread_exit'。我會仔細檢查POSIX線程文檔。 – Codeman

+0

嗯,好吧,看起來如果你運行代碼,孩子在睡覺時因prctl調用而失效(這是本文的重點)。我不想讓孩子在分叉的線程死亡時停止使用。父母過程死後,我想讓孩子失靈。 – user1418199

1

孩子進程死亡,因爲它接收到PR_SET_PDEATHSIG信號,當父線程死亡。這意味着當創建它的線程死亡時它會得到一個信號。所以如果你想讓孩子依賴父進程(我假設你的意思是當「主」函數死掉時)從父進程的主線程執行fork。如果你查看Linux prct(2) man page的手冊頁,他們特別聲明它是創建這個過程的線程,將信號傳遞給調用(在你的情況下是孩子)過程。

底線:從執行的主線程 叉,如果你想讓它依賴於父進程的執行。簡而言之,不要創建一個線程來分支子進程,只需從主線程中分支它即可。

希望這會有所幫助。