[インデックス 12918] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおけるPlan 9オペレーティングシステム向けの終了処理を改善するものです。具体的には、syscall.Exit
が呼び出し元のGoプロセスのみを終了させ、同じプロセスグループ内の他のGoプロセスが残ってしまう問題を解決します。この変更により、syscall.Exit
がruntime·exit
を呼び出すようになり、関連するCL (Change List) https://golang.org/cl/5617048
の変更と合わせて、プロセスグループ内の全てのGoプロセスがクリーンに終了するようになります。
コミット
commit 49a7da2dd94347f0e019e832fd4584c4263bf7ff
Author: Akshat Kumar <seed@mail.nanosouffle.net>
Date: Thu Apr 19 16:31:26 2012 -0700
syscall: cleanly exit all Go procs on Plan 9
syscall.Exit would originally kill only the calling
Go proc, leaving behind other procs in the
same group. This change makes syscall.Exit call
runtime·exit, which due to CL
https://golang.org/cl/5617048
will cleanly exit all the Go procs in the group.
R=golang-dev, rsc, rminnich, remyoudompheng, ality, john
CC=golang-dev, mirtchovski
https://golang.org/cl/6036051
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/49a7da2dd94347f0e019e832fd4584c4263bf7ff
元コミット内容
このコミットの目的は、「Plan 9上で全てのGoプロセスをクリーンに終了させる」ことです。以前のsyscall.Exit
は、呼び出し元のGoプロセスのみを終了させ、同じプロセスグループ内の他のGoプロセスが残存するという問題がありました。この変更により、syscall.Exit
がruntime·exit
を呼び出すようになり、これによりプロセスグループ内の全てのGoプロセスがクリーンに終了するようになります。これは、関連するCL https://golang.org/cl/5617048
によるruntime·exit
の挙動変更と連携しています。
変更の背景
Goプログラムは、複数のゴルーチン(Goの軽量スレッド)を持つことができ、これらはOSレベルでは複数のプロセス(Plan 9では「プロック」と呼ばれる)として実行されることがあります。Plan 9では、プロセスはグループ化され、特定の操作がグループ全体に影響を与えることがあります。
このコミット以前のsyscall.Exit
の実装では、Goプログラムが終了しようとした際に、syscall.Exit
が呼び出された特定のGoプロセス(プロック)のみが終了し、同じGoプログラムに属する他のGoプロセスが終了せずに残ってしまうという問題がありました。これは、リソースリークや予期せぬ挙動を引き起こす可能性があり、プログラムの健全な終了を妨げていました。
この問題は、特にGoプログラムが複数のOSプロセスを生成して並行処理を行う場合に顕著になります。プログラム全体が終了する際には、そのプログラムが生成した全てのOSプロセスが適切に終了することが期待されます。このコミットは、この「クリーンな終了」を実現するために導入されました。
前提知識の解説
- Plan 9 (from Bell Labs): ベル研究所が開発した分散オペレーティングシステムです。Unixの概念をさらに推し進め、全てのリソース(ファイル、デバイス、ネットワーク接続など)をファイルシステムとして表現する「全てはファイル」という哲学を特徴としています。プロセス管理やシステムコールもUnix系OSとは異なる独自のアプローチを持っています。Plan 9では、プロセスは「プロック (proc)」と呼ばれ、プロセスグループの概念も存在します。
- Go言語の
syscall
パッケージ: Go言語の標準ライブラリの一部で、オペレーティングシステムの低レベルなプリミティブ(システムコール)へのインターフェースを提供します。OS固有の機能にアクセスするために使用されますが、通常はos
、time
、net
などの高レベルなパッケージを使用することが推奨されます。syscall
パッケージは、各OS向けに異なる実装を持っています(例:syscall_plan9.go
,syscall_linux.go
など)。 - ゴルーチン (Goroutine): Go言語における軽量な並行処理の単位です。OSのスレッドよりもはるかに軽量で、数千、数万のゴルーチンを同時に実行することが可能です。GoランタイムがゴルーチンをOSスレッドにマッピングして実行を管理します。
runtime·exit
: Goランタイム内部の関数で、Goプログラム全体の終了処理を担当します。この関数は、プログラムの全てのゴルーチンを停止させ、リソースを解放し、最終的にOSに終了ステータスを返します。このコミットで参照されているCLhttps://golang.org/cl/5617048
は、このruntime·exit
の挙動を改善し、プロセスグループ内の全てのGoプロセスをクリーンに終了させるように変更したものです。- アセンブリ言語 (Assembly Language): コンピュータのプロセッサが直接実行できる機械語命令を、人間が読み書きしやすいように記号化した低レベルプログラミング言語です。Go言語のランタイムや一部のシステムコールラッパーは、パフォーマンスやOSとの直接的な連携のためにアセンブリ言語で記述されることがあります。このコミットでは、Plan 9の386アーキテクチャ向けのアセンブリコードが変更されています。
TEXT
ディレクティブ (Goアセンブリ): Go言語のアセンブリファイルで使用されるディレクティブで、関数の開始を宣言します。TEXT funcname(SB), flags, framesize
のような形式で記述され、SB
は静的ベースポインタ、flags
は関数のプロパティ(例:7
はNOSPLIT
とNEEDCTXT
の組み合わせ)、framesize
はスタックフレームのサイズを示します。
技術的詳細
このコミットの技術的な核心は、syscall.Exit
の内部実装を、直接OSの終了システムコールを呼び出すのではなく、Goランタイムのruntime·exit
関数を呼び出すように変更した点にあります。
以前のsyscall_plan9.go
では、Exit
関数はExits
関数を呼び出し、Exits
関数が最終的にPlan 9のexits
システムコール(メッセージを伴う終了)を呼び出していました。このexits
システムコールは、呼び出し元のプロセスのみを終了させる挙動を持っていました。
新しい実装では、syscall_plan9.go
のExit
関数は、アセンブリで定義されたexit
関数を呼び出すように変更されます。このアセンブリのexit
関数(src/pkg/syscall/asm_plan9_386.s
に定義)は、引数として受け取った終了コードをスタックにプッシュし、その後CALL runtime·exit(SB)
命令を使ってGoランタイムのruntime·exit
関数を呼び出します。
この変更により、Goプログラムの終了処理がGoランタイムの制御下に入ります。runtime·exit
は、Goランタイムが管理する全てのゴルーチンと、それらが実行されているOSプロセス(プロック)を適切に終了させるロジックを持っています。特に、このコミットで言及されているCL https://golang.org/cl/5617048
によって、runtime·exit
はPlan 9上でプロセスグループ内の全てのGoプロセスをクリーンに終了させるように強化されています。
これにより、Goプログラムがsyscall.Exit
を呼び出した際に、そのプログラムに関連する全てのOSプロセスが確実に終了し、リソースリークやゾンビプロセスの発生を防ぐことができます。
コアとなるコードの変更箇所
このコミットでは、以下の2つのファイルが変更されています。
-
src/pkg/syscall/asm_plan9_386.s
: Plan 9の386アーキテクチャ向けのアセンブリコードファイル。- 新しい関数
TEXT ·exit(SB),7,$4
が追加されました。この関数は、Goのsyscall.Exit
から呼び出され、最終的にruntime·exit
を呼び出すためのラッパーとして機能します。 MOVL code+0(FP), AX
で引数code
をAX
レジスタにロードします。MOVL AX, 0(SP)
でAX
レジスタの値をスタックにプッシュします(runtime·exit
の引数として)。CALL runtime·exit(SB)
でruntime·exit
関数を呼び出します。
- 新しい関数
-
src/pkg/syscall/syscall_plan9.go
: Plan 9オペレーティングシステム向けのGoのシステムコール実装ファイル。- 既存の
Exits
関数(//sys exits(msg *byte)
とそれに関連するGoコード)が完全に削除されました。 Exit
関数が大幅に簡素化されました。以前はExits
を呼び出して終了メッセージを構築していましたが、新しい実装では単にアセンブリで定義されたexit(code int)
関数を呼び出すだけになりました。func exit(int)
というアセンブリで実装された関数の宣言が追加されました。
- 既存の
コアとなるコードの解説
src/pkg/syscall/asm_plan9_386.s
の変更点
+//func exit(code int)
+// Import runtime·exit for cleanly exiting.
+TEXT ·exit(SB),7,$4
+ MOVL code+0(FP), AX
+ MOVL AX, 0(SP)
+ CALL runtime·exit(SB)
+ RET
TEXT ·exit(SB),7,$4
:exit
という名前のGo関数をアセンブリで定義しています。·exit
: Goのリンカが認識する内部的な関数名です。(SB)
: 静的ベースポインタからのオフセットでアドレス指定されることを示します。7
: 関数のフラグです。この場合、NOSPLIT
(スタックの分割を許可しない) とNEEDCTXT
(コンテキストレジスタが必要) の組み合わせです。$4
: この関数のスタックフレームサイズが4バイトであることを示します。これは、code
引数をスタックにプッシュするために必要なスペースです。
MOVL code+0(FP), AX
:code
という引数(フレームポインタFP
からのオフセット0
にある)の値をAX
レジスタに移動します。code
はsyscall.Exit
に渡された終了コードです。MOVL AX, 0(SP)
:AX
レジスタの値をスタックポインタSP
の指すアドレス(スタックの先頭)に移動します。これは、runtime·exit
関数に渡す引数(終了コード)を準備しています。CALL runtime·exit(SB)
:runtime·exit
関数を呼び出します。この呼び出しにより、Goランタイムの終了処理が開始され、プログラムに関連する全てのGoプロセスがクリーンに終了します。RET
: 関数から戻ります。ただし、runtime·exit
は通常、呼び出し元に戻ることなくプログラムを終了させるため、このRET
命令に到達することは稀です。
src/pkg/syscall/syscall_plan9.go
の変更点
// Implemented in assembly to import from runtime.
func exit(int)
func Exit(code int) { exit(code) }
func exit(int)
: これは、アセンブリファイル(asm_plan9_386.s
)で実装されているexit
関数をGoコードから呼び出すための宣言です。Goコンパイラは、この宣言を見て、対応するアセンブリ関数をリンクします。func Exit(code int) { exit(code) }
: Goのsyscall.Exit
関数が、単にアセンブリで実装されたexit
関数を呼び出すように変更されました。これにより、終了処理のロジックがGoランタイムに一元化され、Plan 9上でのGoプログラムの終了がより堅牢かつクリーンになります。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/49a7da2dd94347f0e019e832fd4584c4263bf7ff
- 関連するGo CL (Change List) 1:
https://golang.org/cl/5617048
(runtime·exitの挙動変更) - 関連するGo CL (Change List) 2:
https://golang.org/cl/6036051
(このコミット自体のCL)
参考にした情報源リンク
- Plan 9 operating system, Go runtime exit, golang syscall packageに関するWeb検索結果
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQG2AzEGygbMpCZPvLrwNFJpwQsUnK4KjN7wnk0tqzPL2-uABwc5aEciQWLc85jHBx8nopeD3JkcTlsFJbAe71Lpvz4DvjGlHxTvCKqrnPQrSlRVSzDv70asxthyANpFy5ltwE6n64xz28s03jDyPAw=
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFZDeOg5oLHOc8iWVzcO253fFkJG-65WH04CEs-hMIeh_AGQpWCUw0kGX4YGCQ7JTA8HSxnhK81Rz7f0e0K8Rkq8qRzsnuy_CnG9oV3g-5ctOU8WLp4aFw2Z9IPEebyeS0YeLg=
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFK0ZKHomL0HgMaOUKO-NccIzJtR4qZETHBNd-fbXeLh3bI1D7dINDWit5lWm8MKEx3hLUKbWmKBA17m-fUl7UP9jVaNPAyUsdyKyLnAdxNvvQy4EdJ9mzCpq2KiBq9eGexyi_UQA==
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGEgNtX3Fiw6ziblIEq4mxnkh64jSpiU-gnjptdS7sOKg76L1hyfy7SrJLWemWhbvLGhuY3k9-uZlSEMXftCUGbUZ2u770lbi0RRayM7b1RZf8was5C3F7_RlDAetk_7eI-tIY=
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQHa0uSX6HzFh16QUDNsWWiIGjPGCb_MvPmxaOP7ejwcJEsgtSQNQTZ9l5VazjHM84vqGmfI1XUCesCgb8YrY-6A0QM2OxTmQhamzna3xYv5sQw_L58=
- https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGweYNrnZLznq1ZKiHLsPV84q9NlhAZrTh6i7Yd7AGAwgEUvoCObVugCK15U0CV4kNMbq4-8jQtWehfAtaQS1fQRguHqB50ZeMh6dIe9_kiw2CrIPXmG84Dqv-Hy0sPBHadaj2lv0XTQtFEQsI=