マルチスレッドのプログラミング

シグナルに関する操作

この節では、シグナルの操作について説明します。

「スレッドのシグナルマスクの設定」

「特定のスレッドへのシグナルの送信」

「特定のシグナルの待機」

「特定のシグナルを指定された時間だけ待機」

スレッドのシグナルマスクの設定

pthread_sigmask(3C) は、sigprocmask(2) がプロセスに対して行うのと同じ処理を、スレッドに対して行います。pthread_sigmask() は、スレッドのシグナルマスクを設定します。新しいスレッドが生成されると、その初期状態のシグナルマスクは生成元から継承されます。

マルチスレッドプロセス内で sigprocmask() を呼び出すのは、pthread_sigmask() を呼び出すのと同等です。詳細は、sigprocmask(2) のマニュアルページを参照してください。

特定のスレッドへのシグナルの送信

pthread_kill(3C) は、スレッド用の kill(2) です。pthread_kill() の呼び出しは、特定のスレッドにシグナルを送ります。特定のスレッドに送られるシグナルは、プロセスに送られるシグナルとは異なります。プロセスに送られたシグナルは、プロセス内のどのスレッドでも処理できます。pthread_kill() で送られたシグナルは、指定されたスレッドだけが処理できます。

pthread_kill() でシグナルを送ることができるのは、現在のプロセス内のスレッドに限られます。スレッド識別子 (thread_t 型) のスコープは局所的であるため、現在のプロセスのスコープにないスレッドは指定できません。

宛先スレッドでシグナルの受信時に行われる処理 (ハンドラ、SIG_DFL、または SIG_IGN) は、通常どおり大域的です。あるスレッドに、あるプロセスを終了させる SIGXXX を送信する場合、宛先スレッドがこのシグナルを受け取った時点でプロセス全体が終了します。

特定のシグナルの待機

マルチスレッドプログラムでは、sigwait(2) が優先インタフェースです。これは、非同期シグナルを正しく処理できるからです。()

sigwait() は、sigwait() 関数の set 引数に指定したシグナルが呼び出しスレッドに送られてくるまで、そのスレッドを待ち状態にします。スレッドが待っている間は、set 引数で指定したシグナルのマスクが解除され、復帰時に元のシグナルマスクが設定し直されます。

set 引数で識別されるすべてのシグナルは、呼び出しスレッドを含むすべてのスレッドでブロックする必要があります。そうしないと、sigwait() は正確に動作しません。

非同期シグナルからプロセス内のスレッドを隔離したい場合は、sigwait() を使用します。非同期シグナルを待つスレッドを 1 つ生成しておき、ほかのスレッドは、現在のプロセスに送られてくる可能性のある非同期シグナルをすべてブロックするようにすることができます。

次の例は、sigwait() の構文を示しています。

#include <signal.h>
int sigwait(const sigset_t *set, int *sig
);

指定のシグナルが送られてくると、sigwait() は保留されているそのシグナルを削除し、sig にそのシグナルの番号を入れます。同時に複数のスレッドから sigwait() を呼び出すこともできますが、受け取るシグナルごとに 1 つのスレッドだけの sigwait だけが返ってきます。

sigwait() では、非同期シグナルを同期的に扱うことができます。こうしたシグナルを扱うスレッドは、sigwait() を呼び出したあと、シグナルが到着するとすぐ終了します。sigwait() の呼び出し側を含むすべてのスレッドで非同期シグナルをマスクすることによって、非同期シグナルを特定のシグナルハンドラだけに安全に処理させることができます。

すべてのスレッドですべてのシグナルを常にマスクし、必要なときだけ sigwait() を呼び出すようにすれば、アプリケーションはシグナルに依存するスレッドに対してはるかに安全になります。

通常はsigwait() を呼び出すスレッドを 1 つ以上作成して、シグナルを待機します。sigwait() はマスクされているシグナルであっても受け取るため、それ以外のスレッドでは誤ってシグナルを受け取ることがないように、対象となるシグナルをすべてブロックしてください。

シグナルを受け取ったシグナル処理スレッドは、sigwait() から復帰してそのシグナルを処理したあと、sigwait() を再度呼び出して次のシグナルを待機します。このシグナル処理スレッドは、非同期シグナル安全関数以外にも使用できます。このシグナル処理スレッドは、ほかのスレッドとも通常の方法で同期をとることができます。非同期シグナル安全カテゴリについては、「マルチスレッドインタフェースの安全レベル」を参照してください。


注 –

sigwait() は、非同期シグナルを受け取れません。


特定のシグナルを指定された時間だけ待機

sigtimedwait(3RT)sigwait(2) に似ていますが、sigtimedwait() は指定時間内にシグナルを受け取らなかった場合に失敗してエラーを返すという点が異なっています。詳細は、sigtimedwait(3RT) のマニュアルページを参照してください。