136

Linuxでは、プログラム(複数のスレッドがある可能性があります)がSIGTERMやSIGHUPなどのシグナルを受信するとどうなりますか?

どのスレッドが信号を傍受しますか?複数のスレッドが同じシグナルを取得できますか?信号の処理専用の特別なスレッドはありますか?そうでない場合、シグナルを処理するスレッド内で何が起こりますか?シグナルハンドラルーチンが終了した後、実行はどのように再開されますか?

4

2 に答える 2

155

pthreads(7)POSIX.1 では、プロセス内のすべてのスレッドが以下を含む属性を共有する必要があると説明しています。

  • 信号処理

POSIX.1 では、次のようないくつかの属性をスレッドごとに区別する必要もあります。

Linux カーネルのcomplete_signalルーチンには、次のコード ブロックがあります。コメントは非常に役に立ちます。

/*
 * Now find a thread we can wake up to take the signal off the queue.
 *
 * If the main thread wants the signal, it gets first crack.
 * Probably the least surprising to the average bear.
 */
if (wants_signal(sig, p))
        t = p;
else if (!group || thread_group_empty(p))
        /*
         * There is just one thread and it does not need to be woken.
         * It will dequeue unblocked signals before it runs again.
         */
        return;
else {
        /*
         * Otherwise try to find a suitable thread.
         */
        t = signal->curr_target;
        while (!wants_signal(sig, t)) {
                t = next_thread(t);
                if (t == signal->curr_target)
                        /*
                         * No thread needs to be woken.
                         * Any eligible threads will see
                         * the signal in the queue soon.
                         */
                        return;
        }
        signal->curr_target = t;
}

/*
 * Found a killable thread.  If the signal will be fatal,
 * then start taking the whole group down immediately.
 */
if (sig_fatal(p, sig) &&
    !(signal->flags & SIGNAL_GROUP_EXIT) &&
    !sigismember(&t->real_blocked, sig) &&
    (sig == SIGKILL || !p->ptrace)) {
        /*
         * This signal will be fatal to the whole group.
         */

したがって、シグナルが配信される場所を担当していることがわかります。

プロセスがシグナルの性質をSIG_IGNまたはSIG_DFLに設定している場合、シグナルはすべてのスレッドで無視されます (またはデフォルト -- kill、core、または ignore)。

プロセスが特定のハンドラー ルーチンにシグナルの性質を設定している場合、 を使用して特定のスレッド シグナル マスクを操作することにより、どのスレッドがシグナルを受信するかを制御できますpthread_sigmask(3)。それらすべてを管理する 1 つのスレッドを指定するか、シグナルごとに 1 つのスレッドを作成するか、特定のシグナルに対してこれらのオプションを任意に組み合わせて作成するか、メイン スレッドにシグナルを配信する Linux カーネルの現在のデフォルト動作に依存することができます。

ただし、signal(7)マニュアルページによると、一部のシグナルは特別です。

シグナルは、プロセス全体 (たとえば、kill(2)を使用して送信される場合) または特定のスレッド (たとえば、実行の結果として生成される SIGSEGV や SIGFPE などの特定のシグナル) に対して生成される (したがって保留中) 場合があります。特定の機械語命令は、 pthread_kill(3)を使用して特定のスレッドを対象とするシグナルと同様に、スレッド向けです )。プロセス向けシグナルは、現在シグナルがブロックされていないスレッドのいずれかに配信される可能性があります。複数のスレッドでシグナルのブロックが解除されている場合、カーネルはシグナルを配信する任意のスレッドを選択します。

于 2012-07-27T00:05:39.480 に答える
42

これは、使用している Linux カーネルのバージョンによって若干異なります。

2.6 posix スレッドを想定し、SIGTERM または SIGHUP を送信する OS について話している場合、シグナルはプロセスに送信され、ルートスレッドによって受信および処理されます。POSIX スレッドを使用すると、SIGTERM を個々のスレッドに送信することもできますが、OS がシグナルをプロセスに送信したときに何が起こるかについて質問していると思われます。

2.6 では、SIGTERM は子スレッドを「正常に」終了させますが、2.4 では、子スレッドは不確定な状態のままでした。

于 2012-07-26T23:42:39.250 に答える