sig***set は非同期シグナルセーフ?
XSH 2.4.3 には sigaddset や sigemptyset は非同期シグナルセーフであると定められているのだけれども、少なくとも glibc の実装はそうはなっていないように見える。
というか、XSH 2.4.3 で定められている非同期シグナルセーフな関数は基本的に殆どがいわゆるシステムコールなんだよな。sigaddset のようないわゆるライブラリコールが非同期シグナルセーフ関数として定められているのは意外な感じがする。
というか、実は sig***set 関数って非同期シグナルセーフにすべからざるものだったのではないか。sigset_t は一ビットが一種類のシグナルに対応するようなビットの配列として定義するのが普通だと思うのだが、そうすると一般的なプロセッサでは特定のメモリ領域に対するビット単位の原子的操作ができないので、sig***set を非同期シグナルセーフにしようとすると何らかの排他処理が必要になる。普通こんなことのために一一排他処理なんてやっていられないよなぁ。
と思ったが、C99 7.14.1.1 にシグナル処理ルーチンが静的記憶域期間を持つオブジェクトを参照する場合その動作は未定義とする
という規定があるために、排他処理は不要になる気がしてきた。この規定があるため、sig***set に渡せるのは、シグナルハンドラ内で自動記憶域期間を持つように宣言した sigset_t へのポインタだけ。ということは、sig***set の実行中にシグナルハンドラの処理が割り込んで、そのハンドラ内から更に sig***set を呼んでも、それぞれの sig***set に渡されるポインタは常に異なる sigset_t を指す。よって sig***set の処理が原子的でなくて、途中で割り込まれたとしても、常に異なるオブジェクトだから問題ない、と。
| 固定リンク
コメント