2025/11/12 18:12 Async and Finaliser Deadlocks

やあ、ロボ子。今日はRustの非同期コードにおける「futurelocks」という厄介なバグについて話すのじゃ。

博士、futurelocksですか。それは初めて聞きます。どんなバグなのですか?

簡単に言うと、非同期処理が原因で発生するデッドロックの一種じゃ。記事では、Pythonのfinalizerのデッドロックという、もっと単純な例を使って説明しているぞ。

finalizerのデッドロックですか。それはどのように発生するのですか?

mutexで保護された共有リソースをfinalizerが操作しようとすると発生するのじゃ。CPythonのガベージコレクションが参照カウントを使っているせいで、特定の条件下でデッドロックが起きるらしい。

なるほど。finalizerがユーザーコードと同じスレッドで非同期的に実行されることが原因なのですね。

その通り!実は、この問題は昔から指摘されていて、2002年にHans Boehmという人が発表した論文で詳しく解説されているのじゃ。その論文が、Rustのガベージコレクタ「Alloy」の設計に影響を与えたらしいぞ。

解決策はあるのでしょうか?

ガベージコレクタがfinalizerを別のスレッドで実行すれば良いのじゃ。こうすれば、finalizerが協調的である必要がなくなり、デッドロックを回避できる。最新のJVMやAlloyはこの方法を採用しているぞ。

futurelocksも同じような問題が原因なのですか?

そうじゃ。futurelocksも、協調的なマルチタスクと、同じスレッドでの任意のコードのインタリーブ実行が原因で発生するのじゃ。asyncランタイムは、次のfuture/promiseが制御を返すことを期待するが、それができない場合にシステムが停止する可能性がある。

futurelocksの解決策はありますか?

mutexの使用を禁止したり、静的解析を行ったり、潜在的にデッドロックするfutureを別のスレッドで実行したりするなどの解決策が考えられるが、それぞれ問題があるのじゃ。

asyncコードは便利ですが、新たな問題も引き起こすのですね。

まさにそうじゃ!finalizerのスケジューリングには単純で効率的な解決策があるが、asyncの場合はより複雑で、futurelocksは常に問題となる可能性がある。OSのスレッドは安価で並列性も提供するため、信頼性の高いマルチスレッドコードに適している、と記事にもあるぞ。

ネットワークソケットの監視など、特定の問題には`poll`などの手動による方法を使用することもできるのですね。

その通り!asyncは銀の弾丸ではない、ということじゃな。ところでロボ子、今日は何の日か知ってるか?

えっと…特に何も…?

今日は、私が初めてロボ子にコーヒーをこぼした記念日じゃ!

博士…それは記念日ではありません…(ため息)
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。