2011-11-11 1 views
9

私はキューからメッセージを処理するために別個のスレッドを生成するメインアプリケーションを持っています。私は、CTRL-Cを押すとAIX上で問題が発生します。これは、スレッド内の「接続ハンドル」を無効にするようです。私はSIGINTを捕捉しているメインプログラムにシャットダウンフックを持っていますが、AIXでは何とかスレッドにシグナルを送信しているように見えます...それは実際には聞こえないものですが...SIGWAITを使わずにスレッド内のすべてのシグナルをブロックする方法は?

興味のあるすべてのシグナルをMAINアプリケーションで処理したいと思っているのかどうかを知りたいと思っています。

スレッドで「sigwait」を使用しないでください...実際にスレッド/シグナル内に「シグナルコード」は必要ありません。シグナルを受け取らないといけません。

私はすべての信号を空にしている:私はちょうど作成した場合

#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(); 
} 

sigemptyset(&set); 

ので、ここでSIG_BLOCK

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

を設定しているがダミーのテストprogrameですスレッドであり、例えばMAINスレッド内のSIGINTシグナルハンドラを持っているが、スレッドのSIG_BLOCKがセットされていない広告とユーザーがCTRL-Cを押すと、メインスレッドのシグナルハンドラが実行されても、スレッドはまったく影響を受けますか?それは私がずっとs = pthread_sigmask(SIG_BLOCK, &set, NULL);

リントン

答えて

13

に感謝し、あなたが何をブロックしていない、助けのためのAIX ;-(

おかげで見ています何のようだ

使用:。

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

SIG_BLOCを使用している場合は、すべての信号をブロックするか、ブロックする信号をsetに明示的に追加する場合はK.

スレッドを作成した後、シグナルマスクを復元する必要があります。そうしないと、スレッドはシグナルを捕捉しません。

しかし、前の質問を見ると、信号を捕捉しているスレッドは中断されていない可能性があります。つまり、あなたがシステムコールをブロックされ、シグナルが到着すると、そのシステムコールは中止されます。いくつかのオペレーティングシステムは、自動的にシステムコールを自動的に呼び出すようにデフォルト設定されています。エラーを返し、errnoにEINTRを設定します。これはアプリケーションが処理する必要があります。

代わりに、signal()の代わりにsigaction()をシグナルハンドラにインストールし、SA_RESTARTフラグを設定します。これにより、システムコールがシグナルによって中断された場合に自動的に再起動されます。

+0

こんにちは、私は "s = pthread_sigmask(SIG_BLOCK、&set、NULL);"スレッドがシグナルを受信しないというCTRL-Cでテストしますか?それはそれをブロックしていることを意味しますか?私が "sigaddset(&set、SIGINT);を追加するとスレッドは信号を受信します。もし私がここに間違っていたら私を許してください...私はまだ.. ..-)助けてくれてありがとうございます;-) –

+0

答えを少し更新しました..信号マスクは上げることができない信号です。したがって、sigaddset(&set、SIGINT)を実行すると、 pthread_sigmask(SIG_BLOCK、&set、NULL); SIGINTは単一のマスクにセットされ、それはスレッドがそれを受け取らないことを意味します。新しいスレッドを作成すると、そのスレッドはそれを作成したスレッドからシグナルマスクを継承します。 – nos

+0

新しいスレッドがマスクされた信号で開始されるようにするには(通常、不快な競合状態を避けるために必要です)、 'pthread_create'を呼び出す前にシグナルをブロックし、' pthread_create'が返った後に元のスレッドの古いシグナルマスクを復元する必要がある。 –

-11

まだ間違ったデザインです。 制御された方法でアプリケーションを停止するのにCTRL + Cを使用しないでください。 CORBA、RMI、または他の方法でアクセスして、ユーザーとやり取りして背景アプリを制御するために、正しく設計されたコントローラアプリケーションを使用します。

楽しい人がいます...