syscall: update Windows SysProcAttr for recent process creation features
要約
概要
Windows版syscall.SysProcAttrに、ジョブオブジェクト・コンソール・デスクトップ・AppContainer・実験的サンドボックスといった新しいプロセス生成パラメータを指定できるフィールドを追加するproposalです。os/execから最新のWindowsプロセス生成機能を利用できるようにすることが目的です。
ステータス変更
likely_accept → accepted
2026-09-09の proposal review で「likely accept」と判定された後、1週間の様子見期間中に新たな異論が出なかったため、2026-09-16に@aclementsによって正式にacceptedとされました。実装は Issue #80415 自体で追跡されます。
技術的背景
現状の問題点
Windowsでは、ジョブオブジェクトへの参加、専用コンソール/デスクトップへの接続、AppContainerによる分離、Microsoftが新たに公開した実験的サンドボックスAPI(Experimental_CreateProcessInSandbox)などを使ってプロセスを起動したい場合でも、syscall.SysProcAttrにはそれらを指定する手段がありませんでした。package syscallは原則凍結方針のため、こうした機能を使うにはos/exec・os・syscallのプロセス生成ロジックを丸ごとフォークする必要があり、非常にコストが高い状態でした。
提案された解決策
Windows用syscall.SysProcAttrに以下のフィールドを追加します。
Jobs []Handle // 非空なら、このジョブオブジェクトリストでプロセスを開始
Console Handle // 非ゼロなら、このコンソールに接続してプロセスを開始
Desktop string // 非空なら、指定デスクトップ上でプロセスを開始
AppContainer *AppContainer // 非nilなら、このメタデータでAppContainerプロセスを作成
Sandbox *Sandbox // 非nilなら、指定されたサンドボックス内でプロセスを開始
新規型AppContainerはWindowsのSECURITY_CAPABILITIES構造体をGoらしく安全にラップしたもの、SandboxはMicrosoftの実験的サンドボックスAPI向けにFlatBuffersエンコード済みの仕様(Spec []byte)を渡すための型です。Sandboxのスペック定義自体はpackage syscallには持たせず、将来の仕様変更に追随しやすいgolang.org/x/sys/windows側に委ねる設計です。
議論の過程で、Jobsが空スライスの場合の扱いが問題になりました。実機検証の結果、Win32 API (UpdateProcThreadAttribute) は空のジョブリストをERROR_BAD_LENGTHで拒否すること、また空リストに意味のある状態は存在しないことが判明し、最終的に「len(Jobs) > 0のときのみPROC_THREAD_ATTRIBUTE_JOB_LISTを設定し、nilと空スライスは同一視する」という単純な実装方針に落ち着きました。
これによって何ができるようになるか
os/execのレベルから、Windows固有の高度なプロセス分離・制御機能を安全な型付きAPIで直接利用できるようになります。
- サンドボックス実行: 実験的な
Experimental_CreateProcessInSandboxが一般提供された際に、Goプログラムからすぐにサンドボックス化されたサブプロセスを起動できる(AIエージェントのサンドボックス化などを想定)。 - リソース制限付きビルド/実行環境:
Jobsフィールドでジョブオブジェクト階層に子プロセスを配置し、CPU・メモリ制限やクリーンアップを行うビルドツール(例: buildbarnのリモート実行)が実装しやすくなる。 - 専用コンソール/デスクトップでのプロセス起動: GUIやCLIのテスト環境を分離したい場合に、既存の裏技的な回避策なしで対応できる。
- AppContainerによる軽量サンドボックス: セキュリティ上重要度の低い権限のみを持つプロセスを、型安全なAPIで生成できる。
コード例
// Before: syscall.SysProcAttrに該当フィールドが無いため、
// os/exec・os・syscall を丸ごとフォークしてCreateProcess呼び出しを差し替える必要があった
// After: 新フィールドを指定するだけでよい
cmd := exec.Command("target.exe")
cmd.SysProcAttr = &syscall.SysProcAttr{
Jobs: []syscall.Handle{jobHandle},
Sandbox: &syscall.Sandbox{
Identity: "my-sandbox",
Spec: sandboxSpecBytes, // FlatBuffersエンコード済み
},
}
err := cmd.Run()
議論のハイライト
- 「時期尚早では」という懸念: @magicalは、
Experimental_CreateProcessInSandboxがMicrosoft公式に「実験的で変更の可能性あり」と明記されている未リリースAPIであり、Goが安定性を重視する以上、時期尚早だと強く反対しました。 - rscによる反論とリスク評価: @rscは、(1)最悪でも「使われなくなった1フィールド」が残るだけで実害が小さいこと、(2)Microsoftは既に
processmodel.dllに実装を出荷しmxcプロジェクトでも採用しているため関数シグネチャレベルの破壊的変更は考えにくいこと、(3)サンドボックス仕様自体はFlatBuffersで進化に対応でき、その詳細はx/sys/windows側で追随可能であること、(4)次のGoリリース(2027年2月)まで時間的余裕があり早期に手を打つ価値があることを説明し、追加を主張しました。 - 他のコアチームメンバーの賛同: @qmunteland @alexbrainmanは、最悪でも非推奨フィールドが残るだけというリスクの小ささと、rsc自身が実装を主導する意思があることを理由に賛成を表明しました。
Jobsの空スライス問題: 実装レビュー中に外部コントリビュータ(@alex-the-third)がbuildbarnでの実運用テストを通じて、Jobs: nilは成功するが空スライスはERROR_BAD_LENGTHで失敗するという非対称な挙動を発見。@aclementsを中心に議論した結果、空ジョブリストに意味のある状態は存在しないと結論づけ、nilと空スライスを同一に扱う仕様に統一されました。- 関連提案の統合: 本proposalは、AppContainerに関する既存提案#65611、ジョブオブジェクトに関する#79927、デスクトップ指定に関する#42836を、より型安全な形でまとめて置き換えるものと位置づけられています。