2017-06-13 47 views
0

在錯誤情況下,我想允許子線程發出一個信號,然後由父線程捕獲該信號。另一個線程然後安全地終止整個過程。我看到的問題是,如果我在創建過程中使用pthread_sigmask阻止子線程接收信號,那麼它引發的信號不會被其他線程看到。這是預期的行爲?我能做些什麼呢?子線程提高它忽略的信號

我檢查了here和其他許多人喜歡它,但他們處理的信號源於外部過程。

示例代碼如下,請原諒在信號處理程序中使用不允許的函數,因爲它便於舉例。我在這裏使用了SIGABRT,因爲它有一個非常明顯的默認處理程序,但如果使用SIGUSR1,行爲是相同的。

#include <unistd.h> 
#include <signal.h> 
#include <iostream> 
#include <thread> 

void sigHandler(int) 
{ 
    std::cout << "Caught signal in " << std::this_thread::get_id() << std::endl; 
} 

void threadMain() 
{ 
    std::cout << "Child is " << std::this_thread::get_id() << std::endl; 
    sleep(1); 
    raise(SIGABRT); 
    std::cout << "Child exiting" << std::endl; 
} 

int main(int argc, char** argv) 
{ 
    std::cout << "Parent is " << std::this_thread::get_id() << std::endl; 
    struct sigaction psa; 
    psa.sa_handler = sigHandler; 
    sigaction(SIGABRT, &psa, nullptr); 
    sigset_t set; 
    sigemptyset(&set); 
    sigaddset(&set, SIGABRT); 
    if (argc > 1) 
    { 
    if (pthread_sigmask(SIG_BLOCK, &set, NULL) == 0) 
     std::cout << "Masking complete" << std::endl; 
    else 
     std::cout << "Failed to mask" << std::endl; 
    } 
    std::thread child(threadMain); 
    if (argc > 1) 
    { 
    if (pthread_sigmask(SIG_UNBLOCK, &set, NULL) == 0) 
     std::cout << "Unmask complete" << std::endl; 
    else 
     std::cout << "Failed to mask" << std::endl; 
    } 
    sleep(2); 
    child.join(); 
} 

如果您編譯

g++ --std=c++11 -lpthread main.cpp -g -o main 

./main運行輸出是:

Parent is 140042782496544 
Child is 140042766427904 
Caught signal in 140042766427904 
Child exiting 

所以信號被抓住了,但孩子(不是父,像我通緝)。如果您有./main 1運行它的輸出是:

Parent is 140070068569888 
Masking complete 
Unmask complete 
Child is 140070052501248 
Child exiting 

即信號堵塞了,所以孩子沒看出來(這是我想要的東西),但家長沒看到。

如何確保信號由小孩撫養並且由父母撫養?

+0

爲什麼不使用C++異常? –

回答

2

manual for raise(3)似乎表明,它發出的信號明確調用線程,而不是整個過程,所以由一個線程提出的信號不會被看出其他:

raise()函數將信號發送到所述主叫進程或線程。在單線程程序就相當於

 kill(getpid(), sig); 

在多線程程序就相當於

 pthread_kill(pthread_self(), sig); 

改變raise(SIGABRT)明確地kill(getpid(), SIGABRT)似乎做你想要什麼,併發送發信號給整個過程,所以它被一些沒有被阻塞的線程捕獲。

+0

這就是解決它,使用殺死是一個很好的解決方案。謝謝! – Obiphil

1

聽起來像你想要提高()有線程通信 - 嗯,它不。所以你想要做的是不可能的。

但是,您可以設置一個變量,或者在處理程序中使用任何其他線程通信來向主線程報告該信號已被引發。

或者,你可以使用pthread_kill ...