📝

macOSでnbdev使用時のエラー対応

2024/06/24に公開

概要

macOSでnbdevを使用した際、以下のエラーが発生しました。

nbdev_prepare
objc[48348]: +[__NSCFConstantString initialize] may have been in progress in another thread when fork() was called.
objc[48348]: +[__NSCFConstantString initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
Traceback (most recent call last):
...
concurrent.futures.process.BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending.

このエラーへの対応に関する備忘録です。

対策

以下を実行すると、上述したコマンドでも問題なく動くようになりました。

export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES

まとめ

同様のことでお困りの方の参考になりましたら幸いです。

以下、参考にしたChatGPTによる回答です。

回答

このエラーメッセージは、macOSの特定の環境でPythonのマルチプロセッシングを使用する際に発生することがあります。特に、macOSでPythonのconcurrent.futuresmultiprocessingライブラリを使用するときに、新しいプロセスを生成するfork()が呼び出されると、問題が起こることがあります。

事象の詳細

エラーメッセージの中で特に注目すべき点は、Objective-Cの文字列クラス(__NSCFConstantString)の初期化中にfork()が呼び出されたことです。fork()は現在のプロセスを複製して新しいプロセスを作るUNIXシステムコールですが、この複製のプロセスでObjective-Cのライブラリやその他の初期化が完了していない状態であると、新しいプロセスで問題が生じます。

macOSでは、特にObjective-Cやその他のシステムライブラリが関与する場合に、プロセスのfork()後にメインスレッド以外で初期化処理が行われると問題が起きやすいです。これは、プロセスがfork()によって複製された後、新しいプロセスが想定外の状態で初期化を試みるためです。

解決策

解決策として提示されているexport OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YESは、この問題を回避するための環境変数です。これを設定することで、fork()を安全でないとみなされる初期化から保護するチェックを無効にし、エラーを回避します。

ただし、この方法はあくまでワークアラウンドであり、根本的な解決にはなっていないため、使用する際はその影響を理解した上で慎重に行う必要があります。プロセスが予期せず終了するリスクを伴うため、他の解決策がない場合に限り使用することが推奨されます。

Discussion