From: Tanaka Akira Date: 2010-05-06T20:02:33+09:00 Subject: [ruby-dev:41184] Re: [Feature #3251] allow to unlock mutex locked by another thread 2010年5月6日1:24 Yusuke Endoh : > 2 について、現状は Thread#raise には以下のような race が存在します。 > > t1: begin 節を実行している > t2: t1.raise する > t1: rescue/ensure 節の実行を開始する > t3: t1.raise する > t1: rescue/ensure 節が実行されないまま再度例外が発生する > これを、Thread#raise の前に Mutex#lock するというルールにすれば、 > race を避けて使うことができるようになります。と思います。 なにか後始末が必要な処理があるとします。 たとえば、open したものは close しないといけないとして、 以下のコードを考えます。 begin f = open(filename) ensure f.close end ここで、open が終了した後、f に代入する前にコンテキストスイッチが起こると どうでしょうか。 コンテキストスイッチの結果、他のスレッドが動いて、上記のコードを動かしている スレッドを raise したとします。 そうすると、ensure 節が実行されるわけですが、close はできません。 なんでかというと、open で生成した IO オブジェクトがどこにも 記録されていないからです。 これは上記の Mutex#lock を使っても防げません。 一回しか Thread#raise していないからです。 というわけで、rescue/ensure 節の中で他から raise されるのをどうにかすれば Thread#raise が安全になる、というわけではありません。 > # ちなみにこの race はシグナルにも存在します POSIX シグナルでは、受け付けたシグナルは signal handler 内でマスクされるので、 handler 内で再度そのシグナルで割り込まれる、という心配はありません。 昔話としてはそうではなかったものもあったようで、その race の話は 検索すれば出てくるかもしれません。 -- [田中 哲][たなか あきら][Tanaka Akira]