From: Masatoshi SEKI Date: 2000-07-26T22:59:53+09:00 Subject: [ruby-list:24024] Re: context switch during finalizer(Re: Re: Flyweight) > |> weakrefは対応します。 > | > |preview 版 1.4.6 は対応されていないようです。 > > あ、1.4系の対応を忘れてた。preview出して正解でしたね。 > Thread.criticalを使って対応します。 preview2 の weakref.rb ですが、 43 def initialize(orig) 44 super 45 @__id = orig.__id__ 46 ObjectSpace.call_finalizer orig 47 ObjectSpace.call_finalizer self 48 ID_MAP[@__id] = [] unless ID_MAP[@__id] 49 ID_MAP[@__id].push self.__id__ 50 ID_REV_MAP[self.id] = @__id 51 end 48行目 が危険そうです。# 検査してからセットしてる。 ID_MAP[@_id] が nil で、複数のスレッドが 48 に入った場合、 48,49でpushした配列を別のスレッドが[]で上書きできます。 48行だけ、あるいは48-50行を Thread.critical にしたほうが良いような…。 --- /usr/local/lib/ruby/1.4/weakref.rb Wed Jul 26 22:06:55 2000 +++ ./weakref.rb Wed Jul 26 22:42:57 2000 @@ -45,7 +45,13 @@ @__id = orig.__id__ ObjectSpace.call_finalizer orig ObjectSpace.call_finalizer self - ID_MAP[@__id] = [] unless ID_MAP[@__id] + begin + __old_status = Thread.critical + Thread.critical = true + ID_MAP[@__id] = [] unless ID_MAP[@__id] + ensure + Thread.critical = __old_status + end ID_MAP[@__id].push self.__id__ ID_REV_MAP[self.id] = @__id end