2017-07-29 23 views
1

シグナルは、任意のスレッドまたはメインプログラム自体で受信できます。 メインプログラムから補助スレッドを1つ作成しました。私のプログラムには2つのスレッドがあります。1.メインスレッド(プロセス自体)2.補助スレッド。私はシグナルが私の補助スレッドに到着するたびに、それが私のメインスレッド(プログラム)にシグナルを送るべきであることを望んでいます。私はpthread_kill(main_threadid、sig)を使用してシグナルハンドラのレジスタから補助スレッド内のシグナルを送信しています。しかし。私はシグナルが補助子自身に受信されたメインスレッドに送信されるたびに観測し、シグナルハンドラは送信シグナルを受信するループに入ります。pthread_kill()は、メインスレッド(メインプログラム)に信号を送信しません。

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

// global variable 
pthread_t main_threadId; 
struct sigaction childpsa; 

// Signal Handler for Auxiliary Thread 
void signalHandler_Child(int param) 
{ 
    printf("Caught signal: %d in auxiliary Thread", param); 
    pthread_kill(main_threadId, param); 
} 

void *childFun(void *arg) 
{ 
    childpsa.sa_handler = signalHandler_Child; 
    sigaction(SIGTERM, &childpsa, NULL); 
    sigaction(SIGHUP, &childpsa, NULL); 
    sigaction(SIGINT, &childpsa, NULL); 
    sigaction(SIGCONT, &childpsa, NULL); 
    sigaction(SIGTSTP, &childpsa, NULL); 

    while (1) { 
     // doSomething in while loop 
    } 
} 

int main(void) 
{ 
    main_threadId = pthread_self(); 

    fprintf(stderr, "pid to signal %d\n", getpid()); 

    // create a auxiliary thread here 
    pthread_t child_threadId; 
    int err = pthread_create(&child_threadId, NULL, &childFun, NULL); 

    while (1) { 
     // main program do something 
    } 

    return 1; 
} 

私は、そのプロセスIDを使用して端末から処理するためにSIGINTを送信していると言っています。

+1

私はあなたが何をしようとしているのか正確には分かりませんが、スレッド間通信にグローバル信号を使用するのはおそらく正しいアプローチではありません。 – thrig

答えて

2

のUnix環境での高度なプログラミングから:

各スレッドは独自のシグナルマスクを持っていますが、信号配置は、プロセス内のすべてのスレッドで共有されています。この は、個々のスレッドがシグナルをブロックできることを意味しますが、スレッドが指定された シグナルに関連するアクションを変更すると、すべてのスレッドがアクションを共有します。したがって、あるスレッドが特定の信号を無視することを選択した場合、別のスレッドはデフォルトの処理を復元するか、信号のシグナルハンドラをインストールすることによって、 を元に戻すことができます。

sigactionコールは、プロセス全体(およびそのプロセス内のすべてのスレッド)のシグナル処理を設定しています。

シグナルをプロセスに送信すると、信号をブロックしていないスレッド(1つのスレッドのみ)がシグナルを受け取ることができます(ただし、限られた経験からメインスレッドが優先されます)。あなたのコードでは、メインスレッドはシグナルを受け取っている可能性が高く、シグナルハンドラを実行してからすぐにシグナルを再び自分自身に送信します。

あなたのプロセスのすべての信号を処理するように単一の補助スレッドをご希望の場合は、問題の信号を遮断するために、あなたのメインスレッドでとpthread_sigmaskを使用することができます。

sigset_t set; 
sigemptyset(&set); 
sigaddset(&set, SIGTERM); 
sigaddset(&set, SIGHUP); 
sigaddset(&set, SIGINT); 
sigaddset(&set, SIGCONT); 
sigaddset(&set, SIGTSTP); 
pthread_sigmask(SIG_BLOCK, &set, NULL); 

これは信号がないことを確認しますそのスレッドに配信されます。 pthread_createの前にこれを行う場合は、補助スレッドでブロックを解除する必要があります。

これで、シグナルなしのスレッド間通信メカニズムを使用して、メインスレッドと通信することができました。

+0

主に "sigaction呼び出しはプロセス全体の信号処理を設定しています"、信号配置と信号マスクについての説明をお寄せいただきありがとうございます。私はちょうど補助スレッドで信号を受信したくないので、すべての信号をメインスレッドだけで受信したいので、子スレッドのpthread_sigmaskを使ってすべての信号をブロックするだけです。今私は(シグナルハンドラを使用して)すべての信号がメインスレッドのみに受信することができます(Thats Great !!)。 whileループを使用して同じ信号を送ると、すべての信号がメインスレッドで受信されますが(それは問題ありません)、端末からすべての送信信号を受信して​​いませんでした –

+0

こんにちはスティーブン、シグナルハンドラを実行し、すぐにシグナルを再び自分自身に送ります。 私のシステムでは、シグナルの100回の試行のために、25シグナル(この数は100試行の異なるセットによって異なります)は子スレッドになり、残りはメインスレッドになります。 –

関連する問題