In article <1109213650.235317.11155.nullmailer / x31.priv.netlab.jp>,
  Yukihiro Matsumoto <matz / ruby-lang.org> writes:

> その指摘の意味は「そのあとの展開でこのリビジョン(1.55)の変更
> は不要になっているはず」が真実でないという意味でしょうか。そ
> れとも、また別の意味?

[ruby-dev:25003] の callcc への対処としては不要になっていますが、他の
問題を防ぐのに有用にもなり得るという意味です。

ここでいう「他の問題」というのは I/O に signal がからんだときのデータ
の蒸発と重複です。

TRAP_BEG, read/write, TRAP_END の順で実行している最中に signal が到着
した場合、タイミングとしては以下の 4通りが考えられます。

(1) read/write が起動する前
(2) read/write の起動中、まだデータが転送されていないとき
(3) read/write の起動中、1byte 以上データが転送されたとき
(4) read/write が終了した後

ここで、(3), (4) の状況で signal が届いた場合、データの転送が既に行わ
れているため、IO バッファの状態を更新すべきです。しかし、signal
handler から ruby コードを直接実行すると、その更新が行われないままに動
作するので、read で読んだものが読まれていないとか、write で書いたもの
が書かれていないなど、一貫性が成り立っていない状態で動作することになり
ます。そのコードが IO オペレーションを行わなければいいのですが、行うと
変なことが起こります。

実の所、現在の実装では TRAP_END の後に IO バッファの状態を更新している
ため更新の前に trap が起動するので、上記の問題は残っているのですが、こ
れは TRAP_END の前に更新するようにすれば修正できます。

しかし、signal handler から ruby コードが直接実行されると、直しようが
なくなってしまいます。

なお、更新のためには read/write の返値が必要なので、signal handler の
中で更新することはできません。また、longjmp も返値が得られないので駄目
です。SA_RESTART を一時的に抜くのはありかもしれませんが毎回やるのはオー
バーヘッドが気になり、さりとてずっとそうしておくのは他のライブラリの迷
惑になります。あと、select で待つのは race condition があります。そし
て nonblocking は fd を他のプロセスと共有していると迷惑になります。

まぁ、sigsafe を使うかそれと同様なことができれば一番いいのですが、これ
はポータブルには出来そうにありません。
http://www.slamb.org/projects/sigsafe/

というように、なかなかいい方法が見つからないのですが、なんかないですか
ね?
-- 
[田中 哲][たなか あきら][Tanaka Akira]