テクノロジー · 実用ガイド

Python 3.14のプロセスプールがサンドボックスで失敗?forkserverのUnixソケットを先に検査

タスクの直列化前に失敗することがあります。一時ディレクトリとAF_UNIXポリシー拒否を分け、spawn、単一worker、または根拠あるコンテキストを選びます。

主プロセスから一時ディレクトリ、AF_UNIXソケット、forkserverまでの診断フロー。
オリジナルイラスト:多重処理の意味を変える前にworker以前の失敗を特定します。 Watch at Ease

Python 3.14は対応POSIXで既定の開始方式をforkからforkserverへ変更しました。別サーバーとローカルUnixソケットを使うため、workerがモジュールを読み込む前に制限環境で失敗できます。

すべてをpickleエラーと呼んだり、forkを自動的な逃げ道にしたりしません。一時領域、AF_UNIX作成・bind、パス長、import安全性、タスク直列化のどこで止まるかを先に確認します。

1. 最初のworkerより前の失敗を特定

sys.version、platform、get_start_method()、完全なトレースバックを記録します。末尾がforkserver.ensure_running、arbitrary_address、gettempdir、listener.bindならユーザー関数は未実行です。

利用可能な一時ディレクトリなし、AF_UNIXパス過長、作成・bind時EPERMを分けます。後段のPicklingErrorやローカル関数AttributeErrorは別の直列化分岐です。

2. 一時ディレクトリとUnixソケットを別々に検査

失敗ジョブと同じサンドボックスとユーザーで使い捨てプローブを実行します。一時ディレクトリにローカルAF_UNIXパスをbindし、終了時に削除します。ネットワークサービスは作りません。

mkdtemp失敗なら一時領域を直すかフォールバックを持つパッチへ更新します。ディレクトリ成功でAF_UNIXがEPERMならTMPDIR変更では権限は増えません。両方成功後に1要素forkserverプールを試します。

3. パッチ版の境界を正しく読む

現行3.14文書では対応POSIXの既定はforkserverで、3.14.9以降は書き込み可能な一時領域がなければspawnです。以前の3.14はOSErrorになり得ます。

この回避は限定的です。書き込み可能でもAF_UNIXが拒否されることがあり、パス長も別問題です。例外、版、パスを保存します。

4. 最小で安全な対応を選ぶ

アプリではget_context('spawn')またはProcessPoolExecutorのmp_contextを試します。workerをモジュール直下に置き、mainガードを使い、pickle可能なデータを渡します。ライブラリは呼び出し側コンテキストを受け取ります。

worker数を指定できるCLIなら単一workerが最小の回避です。並列が必須なら環境管理者に限定的なローカルUnixソケット許可を相談し、外部サービスでポリシーを迂回しません。

forkはスレッドやライブラリ状態の安全を証明したアプリだけで使います。動くプローブは能力を示すだけです。

5. spawnでプログラム意味を再試験

spawnは新しいインタープリタを起動します。入れ子関数やlambdaをimport可能な場所へ移し、入口を保護し、initializerで各workerの資源を作ります。異なるコンテキストのロックは互換でない場合があります。

DB接続、イベントループ、ライブクライアントを渡さず、設定とIDを渡してworker内で開きます。

6. 境界マトリクスで受け入れる

一時ディレクトリ作成、AF_UNIX bind、1要素forkserverプール、1要素spawnプールを記録し、実ツールを単一workerと選択コンテキストで実行して終了コードと成果物ハッシュを保存します。

意図した分岐が成功し、不正な対象が期待どおりimportまたはpickleで失敗し、ソケット残骸がなく、出力が単一worker基準と一致して初めて受け入れます。

forkserver、spawn、forkの要件、失敗シグナル、最初の判断の比較。
オリジナル技術イラスト:開始コンテキストを交換可能なスイッチではなく契約として選びます。 Watch at Ease