PTHREAD_SIGNAL(3) |
FreeBSD Library Functions Manual |
PTHREAD_SIGNAL(3) |
名前
pthread_sigmask, pthread_kill, sigwait -スレッド内でのシグナルハンドリング
書式
#include <pthread.h>
#include <signal.h>
int pthread_sigmask(int
how
, const sigset_t *
newmask
, sigset_t *
oldmask
);
int pthread_kill(pthread_t
thread
, int
signo
);
int sigwait(const sigset_t *
set
, int *
sig
);
説明
pthread_sigmask は呼び出しスレッドのシグナルマスクを引数
how および
newmask で指定されるように変更する。
oldmask が
NULL でないときには、直前のシグナルマスクが
oldmask で指し示される領域に格納される。
引数
how および
newmask の意味は
sigprocmask(2) の引数の意味と同じである。
how が
SIG_SETMASK のときには、シグナルマスクが
newmask に設定される。
how が
SIG_BLOCK のときには、
newmask で指定されるシグナルが現時点のシグナルマスクに追加される。
how が
SIG_UNBLOCK のときには、
newmask で指定されるシグナルが現時点のシグナルマスクから取り除かれる。
シグナルマスクはスレッドごとに設定されることを思い出してほしい。しかし
sigaction(2) で設定されるシグナルアクションとシグナルハンドラは、すべてのスレッドで共通である。
pthread_kill はシグナル番号
signo のシグナルをスレッド
thread に送信する。シグナルは
kill(2) に書かれているように配送されハンドルされる。
sigwait は
set で指定されるシグナルのうちいずれか 1 つが呼び出しスレッドに配送されるまで呼び出しスレッドの実行を停止する。そして受信したシグナルの数を
sig で指し示される領域に格納して返る。
set で指定されるシグナルは
sigwait に入るときにブロックされていなければならず、無視されてはならない。配送されたシグナルに対するシグナルハンドラが登録されていても、ハンドラ関数は呼び出され
ない 。
取り消し
sigwait は取り消しポイントである。
返り値
成功すると、0 が返る。失敗の場合、非 0 のエラーコードが返る。
エラー
関数
pthread_sigmask はエラーのとき、次のようなエラーコードを返す:
-
EINVAL
-
how が
SIG_SETMASK および
SIG_BLOCK 、
SIG_UNBLOCK のいずれでもない。
-
EFAULT
-
newmask または
oldmask が無効なアドレスを指している。
関数
pthread_kill はエラーのとき、次のようなエラーコードを返す:
-
EINVAL
-
signo は有効なシグナル番号でない。
-
ESRCH
-
スレッド
thread は存在しない (例えば、そのスレッドはすでに終了している) 。
関数
sigwait がエラーを返すことはない。
著者
Xavier Leroy <Xavier.Leroy@inria.fr>
関連項目
sigprocmask(2),
kill(2),
sigaction(2),
sigsuspend(2).
注意
sigwait が確実に機能するように、配送を待つシグナルは、呼び出しスレッドだけでなくすべてのスレッドでブロックされていなければならない。そうでない場合、POSIX のシグナル配送機構はシグナルを受信するスレッドが
sigwait を呼び出しているスレッドとなることを保証しない。これを実現する最もよい方法は、どのスレッドを生成するよりも前にそれらのシグナルをブロックし、プログラム中では
sigwait を呼び出す以外、ブロックを解除しないことである。
バグ
LinuxThreads のシグナルハンドリングは POSIX 標準とは大きく異なっている。 POSIX 標準によると、「非同期の」 (外部の) シグナルはプロセス全体 (すべてのスレッドの集まり) に対して発行され、その後特定の 1 つのスレッドに配送される。実際にシグナルを受信するスレッドはその時点でシグナルをブロックしていないスレッドのいずれかとなる。
LinuxThreads では、それぞれのスレッドが実際には固有の PID をもつカーネルプロセスであるため、外部のシグナルは特定の 1 つのスレッドに直接配送される。例えば、もし別のスレッドが
sigwait を使ってそのシグナルをブロックしても、そのスレッドが再開されることはない。
sigwait の LinuxThreads の実装では、
sigwait は待ちの期間中、
set に含まれるシグナルに対応するダミーのシグナルハンドラを登録する。シグナルハンドラはすべてのスレッドで共通であるため、他のスレッドはこれらのシグナルに対して独自のシグナルハンドラを登録してはならない。あるいはその代わりに、すべてのスレッドがこれらのシグナルをブロックしなければならない (このことはとにかく推奨されている -- 注意のセクションを参照のこと) 。