2017-08-04 27 views
1

我正在寫一個多線程程序,需要使用以下的bash行終止處理SIGQUIT SIGUSR1,並忽略其他SIGQUIT。 要忽略我寫了這個信號:與調用sigwait

struct sigaction s; 
s.sa_handler=SIG_IGN; 
if((sigaction(SIGQUIT,&s,NULL))==-1) { 
    perror("sigaction"); 
    return -1; 
    } 

我寫在指定的等待信號(handlerrno是檢查errno和退出功能)線程以下代碼:

sigset_t threadset; 
int err, sig; 
if(sigfillset(&threadset)==-1) handlerrno("Sigfillset thread stats"); 
if(sigdelset(&threadset,SIGQUIT)==-1) handlerrno("Sigdelset thread stats"); 
if(sigdelset(&threadset,SIGINT)==-1) handlerrno("Sigdelset thread stats"); 
if(sigdelset(&threadset,SIGTERM)==-1) handlerrno("Sigdelset thread stats"); 
if(sigdelset(&threadset,SIGUSR1)==-1) handlerrno("Sigdelset thread stats"); 
if((err=pthread_sigmask(SIG_SETMASK,&threadset,NULL))!=0)   
    handlerror(err,"Set sigmask thread stats"); 
if((err=sigwait(&threadset,&sig))!=0) handlerror(err,"Sigwait"); 
//I handle the signals here 

然而,當我從shell啓動SIGQUIT時,指定等待信號的線程似乎卡在sigwait()中,所以我不知道會發生什麼以及哪個線程獲取信號。 代碼有什麼問題嗎?謝謝!

回答

1

忽略掩碼是全過程。在撥打sigaction後,SIQUIT永遠不會在任何線程中掛起,因此sigwait將永遠阻塞。

你應該做的是在創建任何線程之前阻塞主線程中的信號,以便子線程也阻止它(child threads inherit the signal mask of their parent thread)。

處理線程應該能夠使信號出隊,儘管它被阻塞了。

(我不知道你的終止信號的選擇是否是一個很好的一個。SIQUIT通過Ctrl+\正常發送,預計將創建一個核心轉儲終止前,也許SIGTERM會是一個更好的選擇。)

+0

謝謝!我需要終止這樣的過程,因爲這是大學的任務,所以我們的老師給了我們一個測試腳本,以確保代碼的工作。 無論如何,問題在於處理線程是由主線程產生的,所以如果我在那裏阻塞處理線程,它也會阻止它? – Gixuna

+0

正確。如果沒有線程解除阻塞,並且在進程中只有一個sigwait調用處於活動狀態,那麼sigwait調用應該會得到它。 – PSkocik

+0

它的工作,非常感謝! – Gixuna