Bug-org 1052343 [TSF] crash in msctf.dll@0x2efce
初回投稿日時: 2014年09月25日00時02分04秒
カテゴリ: Mozilla Core Mozilla35 TSF Windows バグ修正
SNS:
Tweet (list)
Bug-org 1053048のテストケースの<textarea>
要素でEnterキーをTSFモードで押すと、長時間起動していたPCでは、ランダムにクラッシュするというバグを見つけました。
クラッシュ自体は、OnLockGranted()
を呼び出している間に、TSF内部でクラッシュしていたので、ある意味、TSFのバグと言えそうです。
問題のテストケースでは、Enterキーを押した時に、<textarea>
要素がリサイズされるため、一旦、フォーカスを失い、また、フォーカスを再度得る、という動作になるのですが、OnLockGranted()
を呼び出し中にフォーカスを失うことで、nsTextStore::Destroy()
が呼び出され、nsTextStore
が生成・保持していたTSFのオブジェクトの参照をやめた際に、実際に、それらのオブジェクト自体が解放されているようでした。
つまり、TSF内部で直接参照しているこれらのうちのいずれか、もしくは全てが、TSF内部でstrong referenceではなく、weak referenceで管理されていることを意味します。つまり、OnLockGranged()
を呼び出している間は、ITextStoreACP
インターフェースの実装側、つまり、アプリは、自信が生成したオブジェクトを手放してはいけない、ということになります。
これを解決するために、このバグでは、根本的な挙動に修正を入れました。
これまでは、nsTextStore
は、プロセス起動時にひとつだけ生成され、エディタがフォーカスを持っている間のみ、必要なTSFのオブジェクトを生成して保持し、エディタがフォーカスを失った際に、それらを解放していました。ですが、この疑似シングルトンのような挙動では複雑なケース、例えばドキュメントがロックされている最中にフォーカスが複数回移動するようなケースがあると、破綻しそうです。
そこで、エディタがフォーカスを得る度に、nsTextStore
を生成し、sEnabledTextStore
で掴んでおくようにし、フォーカスを失った際には、sEnabledTextStore
がそれまでのnsTextStore
のインスタンスを手離し、参照カウントがそのままゼロになったら完全に破棄されるようにしました。これで、メンバの複雑な管理には悩まされずに済みます。
続いて、OnLockGranted()
を呼び出す前に、nsTextStore
自身のインスタンスをスタック上のnsRefPtr
で掴んでおき、sEnabledTextStore
が手放しても、参照カウントが絶対にゼロにならないようにし、OnLockGranted()
の呼び出し中は、各種インスタンスが解放されないようにしました。
そして、sEnabledTextStore
がクリアされる直前には今まで通り、nsTextStore::Destroy()
を呼び出しますが、Destroy()
は、ドキュメントをロック中には呼び出された場合には、これを表すフラグを立てるだけにし、実際にメンバの解放は行わないようになりました。その後、RequestLock()
の処理が全て終わってから(ドキュメントのロックが解除されてから)、このフラグが立っている場合には、再度Destroy()
を呼び出し、クリーンナップを行うようにしました。
まとめると、nsTextStore
は、エディタがフォーカスを得た際に生成され、エディタがフォーカスを失う際に解放されますが、RequestLock()
が呼び出されている最中にフォーカスを失った場合のみ、直ちに解放されず、処理が完了後に自動的に解放されます。