ひ to り go と

知らずに回る Run Loop にご用心

MacDev

CotEditor 2.1.6 リリース!

以前記事を書いて紹介したように(→ 2015.2.19)何年も愛用している OS X 用プレーンテキストエディタである CotEditor。最新バージョンの 2.1.6 がリリースされた。

→ CotEditor -Text Editor for OS X

変更点を見てみると:

いくつか前のバージョンから保存時にフリーズするという問題があったのだけど、ほとんどの人はこれで直ると思います。

...という自慢でした。😤

-[NSTask waitUntilExit] の罠

自慢するだけなのもあれなので、今回の問題を引き起こしていた原因を同じバグで悩んでいる開発者のためにメモしておく。

CotEditor ではファイルの読み書きに authopen というコマンドを使うような構造になっているのだけど、それを Cocoa から呼び出すために NSTask というクラスが使われている。保存するデータをそこに投げたあと、処理を待つために呼ばれていたのが -waitUntilExit というメソッド。

waitUntilExit という名前の通り、アプリケーションの処理を休んでコマンドが終了するのを待ってくれるものかと思いきや、ヘッダファイルのコメントを読むと罠があった。

// poll the runLoop in defaultMode until task completes

Run Loop が回るらしい。...ということはこの待ち時間の間、先にセットされていたタイマーの時間が来たらその処理が次々と割り込んでくることになる!

CotEditor の場合、ファイルの保存で authopen が処理をしている中、その処理を待つ間に自動保存のタイマーが発動してしまい、予期せぬタイミングでもう一つの保存が実行されてしまっていた。それが結果的にフリーズを引き起こしていたのだ。

対策は簡単で、このメソッドを使わず単純なループで待つようにすればいい:

while (task.isRunning) usleep(200);

Wait 処理を使うときはどんな仕組みで待っているのか注意しましょう。

Share

(参考になったらぜひ。記事を書くモチベーションの向上に役立てます。)