2016-08-03 12 views
1

親スレッドから2つの子スレッドを作成したコードを記述しました。メインスレッドが終了した後に子スレッドが生きているのはなぜですか?

次に、これらの子スレッド内の別の端末からの信号を受信して​​、threadIDを印刷してスレッドを終了しました。

私には2つの質問があります。

  1. 子スレッドからの信号を受信して​​います。親スレッドのthreadIDをなぜ印刷していますか?

  2. 親スレッドを終了した後、どのように子スレッドを生き延びることができますか?

コード:

最初の3行は3つのthreadID Sであり:ここ

void sig_handler(int signo) 
{ 
    if (signo == 1){ 
     printf("%d\n", pthread_self()); 
     pthread_exit(NULL); 
    } 
} 

void* doSomeThing(void* arg) 
{ 
    printf("In function -> %d\n", pthread_self()); 
    if (signal(1, sig_handler) == SIG_ERR) 
     printf("\ncan't catch SIGHUP\n"); 
    while(1) 
     sleep(1); 
    return NULL; 
} 

int main(int argc, char *argv[]) 
{ 
    printf("In function -> %d\n", pthread_self()); 
    char *ch1; 
    pthread_t tid1, tid2; 
    ch1 = "random"; 
    int ret1, ret2; 

    ret1 = pthread_create(&tid1, NULL, &doSomeThing, (void *) ch1); 
    ret2 = pthread_create(&tid2, NULL, &doSomeThing, (void *) ch1); 

    while(1) 
     sleep(1); 
    return 0; 
} 

は、端末に指定された出力の画像です。最初の1つはメインthreadIDで、次に2つのセカンダリスレッドです。

次に、threadIDは、次のコードブロックから印刷されます。

if (signo == 1){ 
    printf("%d\n", pthread_self()); 
    pthread_exit(NULL); 
} 

なぜこれが起こっていますか?

+1

「signal」はスレッドで実際には機能しません。 –

+0

これは、 'pthread_self()'関数が適切な 'threadID'を与えていないことを意味しますか? 'シグナル 'を受け取った後に呼び出されるので?? – jbsu32

+1

@JishnuBanerjee 'pthread_self()'は、呼び出し元スレッドのスレッドIDを返します。しかし、本当の問題は、スレッドごとのシグナルハンドラを持つことができないということです。信号処理はプロセス全体に及ぶ。シグナルをブロックする方法については、リンクされたマニュアルページの例を参照してください。 –

答えて

3

シグナルはプロセスに配信され、個々のスレッドには配信されません。したがって、ここでやっているように、シグナルハンドラを1つのスレッドに対してだけ持つことはできません。 できることは、pthread_sigmask()を使用したい信号をブロックし、最も一般的な方法であるsigwait()を使用して専用スレッドが信号を処理するようにすることです。

+1

sig_handler()はここでどのように正確に呼び出されますか? sig_handler()が呼び出されるたびにOPが別のthreadIDを取得する、つまりOPがシグナルを送信することを意味します。 この特定のプログラムは、実際にこれらの信号に対してどのように管理/動作しますか? –

+1

OPによって送信された信号は、スレッド固有のものではありません。それはプロセス全体にわたるものです。したがって、信号がどのスレッドに配信されるのかを確かめることはできません。 'pthreads(7)'は次のように言っています: "POSIX.1は、プロセス全体に向けられたシグナルと個々のスレッドに向けられたシグナルの概念を区別しています。 (2)など)は、プロセス内で任意に選択された単一のスレッドで処理する必要があります。この「任意のシグナル配信」は、任意のスレッドがシグナルを受信して​​シグナルハンドラを呼び出し、そのthreadIDが印刷されることを意味します。 –

0

さらに、信号ハンドラ内からasync-signal-safe関数を安全に呼び出すことができます。 the Linux signal man pageから:

非同期シグナル安全機能

シグナルハンドラ関数は、他の場所で実行プログラムの にいくつかの任意の点で中断することができる を処理するので、非常に注意しなければなりません。 POSIXには「安全な機能」という概念があります。 信号は、安全でない関数の実行を中断し、ハンドラ いずれかの危険な関数を呼び出すかハンドラlongjmp()またはsiglongjmp()への呼び出しによって終了し、プログラムがその後のその後の行動、 危険な関数を呼び出す場合プログラムは未定義です。

リンクされたマニュアルページには、シグナルハンドラ内で安全に呼び出せる関数のリストがあります。その機能がそのリストにない場合、それはと呼ばれる安全ではないです。例外なく。

printf()pthread_exit()も非同期シグナルセーフ機能のリストにはないことに注意してください。

  • 任意のコントロールの下で、一般的ではありません終了したスレッド:

    そして、シグナルハンドラ内からpthread_exit()を呼び出すには、いくつかの他の問題を作成します。多くの場合、信号はスレッドにに配信されます。

  • 終了スレッドはオブジェクトを未知の状態にしておくことができます。たとえば、存在しなくなったスレッドによってミューテックスをロックしたままにすることができます。

  • 任意のスレッドクリーンアップハンドラregistered with pthread_cleanup_push()は、シグナルハンドラコンテキスト内から呼び出されます。

関連する問題