操作
致命的 #753
完了WeakStorageのキーが削除されない
開始日:
2015-03-01
期日:
進捗率:
0%
プラグイン名:
説明
Ruby2.1.0以降でWeakStorageからキーが削除されなくなっており、以下のようなフロー(一例)で、プロフィール画面のツイートが表示されないなどの問題が発生しています。
- UserStream経由でユーザAのMessageが取得され、Home TLに流れてくる。
- Home TLの表示可能数がいっぱいになったため、MessageがHome TLから削除され、GCされる。
- 削除されたMessageと同じobject_idをもつ、別のオブジェクトが生成される(object_idはオブジェクトのアドレスとほぼ同じものなので、このような状況は頻繁に発生します)。
- ユーザAのプロフィールを表示しようとする。
- ユーザAの最新ツイートを元に、Message.new_ifnecessaryによってMessageが取得される。
- (キーが削除されていないので)WeakStorage#[]で対応するオブジェクトを取得しようとする。
- 実際には3.で違うオブジェクトが入っているので、type_strictに引っかかる。
- 例外が投げられ、ユーザTLは取得できなかったことになる。
Ruby2.1.0からファイナライザがシグナル割り込みと同じコンテキストで実行されるようになったため、finalizerの中でMonitorを使ったロックができなくなった(ロックしようとすると例外が投げられる・finalizer内の例外は握りつぶされる)ことが原因だと思われます。
参考: https://gist.github.com/osak/71648a7360d9a0a34f57
Rubyの実装を追いきれてないですが、Hash#delete_ifはI/Oじゃないので、途中でWeakStorage#[]とかに割り込まれて変なことになる恐れはない気がするので、とりあえずfinalizer中でのロックを外して様子を見てみます。
バックトレース
ɛ ʘɞʘ ɜ
操作