2011-11-11 46 views
9

我有一個主應用程序,生成一個單獨的線程來處理隊列中的消息。當我點擊CTRL-C時,我在AIX上遇到問題,因爲它似乎使線程中的某些「連接句柄」變得無效。我在捕獲SIGINT的主程序中有一個關閉鉤子,但在AIX上,它似乎以某種方式向該線程發送了一個信號......雖然從我聽到的內容來看,這並不是真的可能...如何在不使用SIGWAIT的情況下阻塞線程中的所有信號?

本質上,想知道我是否希望MAIN應用程序能夠處理我感興趣的所有信號,並讓線程從不處理任何信號......這是「良好實踐」嗎?

如果是這樣我怎麼能不在線程中使用「sigwait」......實際上我不想在線程中有任何「信號代碼」......它們根本不會收到任何信號。

我已經清空了所有的信號:

sigemptyset(&set); 

,並且已經設置了SIG_BLOCK

s = pthread_sigmask(SIG_BLOCK, &set, NULL); 

因此,這裏是一個僞測試PROGRAME:

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 
#include <errno.h> 

#define handle_error_en(en, msg) do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) 

static void * threadMainLoop(){ 
    //Here I do not want the thread to use "sigwait".... 
    while(running == TRUE){ 
     //do some thread work and never have any signals come in 
    } 
} 

void shutdownHook(int sig){ 
    printf("\nCtrl-C pressed....shutdown hook in main...\n"); 
} 

void signalErrorHandler(int signum){ 
    printf("\nSignal error handler in main...\n"); 
} 

int main(int argc, char *argv[]){ 
    pthread_t thread; 
    sigset_t set; 
    int s; 

    //Catch the following signals in the MAIN thread 
    (void) signal(SIGINT, shutdownHook); 
    (void) signal(SIGSEGV, signalErrorHandler); 
    (void) signal(SIGBUS, signalErrorHandler); 
    (void) signal(SIGILL, signalErrorHandler); 
    (void) signal(SIGTERM, signalErrorHandler); 
    (void) signal(SIGABRT, signalErrorHandler); 

    sigemptyset(&set); //BLOCK all signals 

    s = pthread_sigmask(SIG_BLOCK, &set, NULL); 
    if (s != 0) 
     handle_error_en(s, "pthread_sigmask"); 

    s = pthread_create(&thread, NULL, &threadMainLoop, (void *) NULL); 
    if (s != 0) 
     handle_error_en(s, "pthread_create"); 

    pause(); 
} 

如果我剛剛創建一個線程,並且例如在主線程中具有SIGINT信號處理程序,但沒有將SIG_BLOCK設置爲廣告和用戶點擊CTRL-C ....即使主線程中的信號處理程序運行,線程是否也會受到影響?這似乎是我所看到的在AIX上;-(

感謝您的幫助,非常感謝

林頓

回答

13

隨着s = pthread_sigmask(SIG_BLOCK, &set, NULL);,你不阻止任何

使用:

sigfillset(&set); 
sets = pthread_sigmask(SIG_SETMASK, &set, NULL); 

如果您想要阻止每個信號,或者如果您使用的是SIG_BLOC,則明確地將要阻止的信號添加到set K.

創建線程後,您需要恢復信號掩碼,否則沒有線程會捕獲任何信號。

但是,看看你以前的問題,可能是線程捕捉信號不處理被中斷。也就是說,如果系統調用被阻塞,並且信號到達,系統調用會中止。有些操作系統默認會自動再次調用系統調用,有些會返回錯誤並將errno設置爲應用程序必須處理的EINTR - 如果沒有處理,可能會發生不好的事情。

而是使用sigaction()而不是signal()來安裝信號處理程序,並設置SA_RESTART標誌,這會導致系統調用在信號中止時自動重啓。

+0

您好,但它設置「s = pthread_sigmask(SIG_BLOCK,&設置,NULL);」並用CTRL-C測試線程不接收信號?這意味着它阻止了它?如果我添加「sigaddset(&set,SIGINT);」那麼線程收到信號。原諒我,如果我在這裏錯了...我仍然在學習...... ;-)感謝您的幫助;-) –

+0

更新了答案一點..信號掩碼是無法提出的信號。所以如果你做sigaddset(&set,SIGINT); pthread_sigmask(SIG_BLOCK,&set,NULL); ,SIGINT將設置在singnal掩碼中,這意味着線程不會收到它。如果您創建一個新線程,該線程會從創建它的線程繼承信號掩碼。 – nos

+0

請注意,如果你想要一個新的線程以掩碼的信號開始(通常是避免討厭的競態條件所必需的),你需要在調用'pthread_create'之前阻止信號,然後在'pthread_create'返回之後恢復原始線程中的舊信號掩碼。 –

-11

仍然錯誤的設計。 不要使用CTRL + C以受控方式停止應用程序。 使用一個設計正確的控制器應用程序,可通過CORBA,RMI或其他一些方法與用戶進行交互並控制後臺應用程序。

玩得開心的傢伙......

相關問題