[インデックス 19287] ファイルの概要
このコミットは、Go言語のテストスクリプトである race.bash
と race.bat
において、テスト実行前に環境変数 GOROOT_FINAL
を解除する変更を導入します。これにより、特に runtime/debug
パッケージのテストが GOROOT_FINAL
の設定によって失敗する問題を解決し、Goのレース検出ビルドの信頼性を向上させます。
コミット
commit 5d25189d801d7e8bf2fe10ffe95d43dda648a6b0
Author: Alex Brainman <alex.brainman@gmail.com>
Date: Wed May 7 16:34:21 2014 +1000
race.bash,race.bat: unset GOROOT_FINAL during tests
Just like run.* scripts do.
Fixes race build.
LGTM=dave, dvyukov
R=dvyukov, dave
CC=golang-codereviews
https://golang.org/cl/98980043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5d25189d801d7e8bf2fe10ffe95d43dda648a6b0
元コミット内容
race.bash,race.bat: unset GOROOT_FINAL during tests
Just like run.* scripts do.
Fixes race build.
LGTM=dave, dvyukov
R=dvyukov, dave
CC=golang-codereviews
https://golang.org/cl/98980043
変更の背景
このコミットの背景には、Go言語のビルドシステムにおける GOROOT_FINAL
環境変数の挙動と、runtime/debug
パッケージのテストの要件との間の不整合がありました。
Goのビルドプロセスでは、GOROOT_FINAL
は、Goツールチェインがビルドされた場所とは異なる最終的なインストール場所を指定するために使用されることがありました。この変数が設定されていると、Goツール(cmd/go
やその他のバイナリ)は、その値に基づいて自身の GOROOT
(Goのインストールルート)を特定しようとします。これは、ビルド環境と実行環境が異なる場合に、ツールが正しく動作するために重要でした。
しかし、runtime/debug
パッケージは、スタックトレースの生成など、実行時にソースコードのパスに正確にアクセスする必要があります。もし GOROOT_FINAL
が設定されており、その値がテスト実行時の実際のソースコードの場所と一致しない場合、runtime/debug
のテストがソースファイルを見つけられずに失敗するという問題が発生していました。
コミットメッセージにある「Just like run.* scripts do.」という記述は、Goの他のテスト実行スクリプト(run.bash
など)では既に同様の問題を回避するために GOROOT_FINAL
を解除する処理が行われていたことを示唆しています。このコミットは、レース検出器を有効にしたビルド(go test -race
)を実行する race.bash
および race.bat
スクリプトにも同様の修正を適用することで、この不整合を解消し、レース検出ビルドの安定性を確保することを目的としています。
前提知識の解説
GOROOTとGOROOT_FINAL
- GOROOT: Go言語のインストールディレクトリのルートパスを指す環境変数です。Goのツールチェイン(コンパイラ、リンカ、標準ライブラリなど)は、このパスを基準にファイルを探します。通常、Goをインストールすると自動的に設定されるか、ユーザーが手動で設定します。
- GOROOT_FINAL: Go 1.x系の初期の頃に存在した環境変数で、Goツールチェインをビルドした場所と、最終的にインストールして使用する場所が異なる場合に利用されました。
GOROOT_FINAL
が設定されていると、Goのバイナリ(go
コマンドなど)は、このGOROOT_FINAL
の値を自身の内部に埋め込み、実行時にその埋め込まれたパスをGOROOT
として使用しようとしました。これにより、ビルド後にGoのインストールディレクトリを移動しても、ツールが正しく動作することが期待されました。しかし、このメカニズムは複雑さを増し、しばしば予期せぬ問題を引き起こす原因となりました。Go 1.9以降、cmd/go
はos.Executable
を使用して自身の場所を特定し、そこからGOROOT
を導出するようになり、GOROOT_FINAL
への依存度が低下しました。Go 1.21では、GOROOT_FINAL
の明示的なサポートはGoのビルドシステムからほぼ削除されています。
Goのレース検出器 (Race Detector)
Goには、並行処理におけるデータ競合(race condition)を検出するための組み込みのツールである「レース検出器」があります。これは、go build -race
や go test -race
のように -race
フラグを付けてビルドまたはテストを実行することで有効になります。レース検出器は、実行時にメモリへのアクセスを監視し、複数のゴルーチンが同時に同じメモリ位置にアクセスし、少なくとも1つのアクセスが書き込みであり、かつそれらのアクセスが同期メカニズムによって保護されていない場合に警告を発します。これにより、デバッグが困難な並行処理のバグを早期に発見できます。
runtime/debug パッケージ
runtime/debug
パッケージは、Goプログラムのデバッグ情報にアクセスするための機能を提供します。主な機能には以下のようなものがあります。
- スタックトレースの取得:
runtime.Stack()
関数は、現在のゴルーチンのスタックトレースをバイトスライスとして返します。このスタックトレースには、関数呼び出しの履歴、ファイル名、行番号などが含まれます。 - ビルド情報の取得:
runtime/debug.BuildInfo
構造体を通じて、Goモジュールのパス、バージョン、ビルド時のGoバージョン、コンパイラフラグなどのビルド情報を取得できます。 - GC情報の制御: ガベージコレクションの動作に関する情報や制御を行う関数も提供します。
runtime/debug
がスタックトレースを生成する際には、ソースコードのファイルパスと行番号を正確に参照する必要があります。
技術的詳細
このコミットが解決しようとしている技術的な問題は、GOROOT_FINAL
が設定されている環境で go test -race
を実行した際に、runtime/debug
パッケージのテストが失敗するというものです。
具体的には、runtime/debug
パッケージがスタックトレースを生成する際、またはその他のデバッグ情報を取得する際に、ソースコードのファイルパスを解決しようとします。もし GOROOT_FINAL
が設定されており、その値がGoのソースコードが実際に存在するパスと異なる場合、runtime/debug
は誤ったパスを検索したり、ソースファイルを見つけられなかったりする可能性があります。これにより、runtime/debug
のテストが期待通りの結果を返せず、失敗に至ります。
race.bash
と race.bat
は、Goのレース検出器を有効にしたビルドとテストを実行するためのスクリプトです。これらのスクリプトが go test -race std
を実行する前に GOROOT_FINAL
を解除することで、runtime/debug
パッケージは、Goツールチェインが現在実行されている環境(つまり、テストが実行されている実際のGoのインストール場所)に基づいてソースコードのパスを正しく解決できるようになります。これにより、GOROOT_FINAL
の設定に起因するテストの失敗が回避され、レース検出ビルドのCI/CDパイプラインや開発環境での安定性が向上します。
この修正は、Goのビルドシステムにおける環境変数の取り扱いに関する一般的なプラクティス、すなわち、テストの実行においては可能な限りクリーンな環境を確保するという原則にも合致しています。
コアとなるコードの変更箇所
src/race.bash
--- a/src/race.bash
+++ b/src/race.bash
@@ -38,5 +38,11 @@ fi
# golang.org/issue/5537 - we must build a race enabled cmd/cgo before trying to use it.
go install -race cmd/cgo
go install -race std
+# we must unset GOROOT_FINAL before tests, because runtime/debug requires
+# correct access to source code, so if we have GOROOT_FINAL in effect,
+# at least runtime/debug test will fail.
+unset GOROOT_FINAL
+#
go test -race -short std
go test -race -run=nothingplease -bench=.* -benchtime=.1s -cpu=4 std
src/race.bat
--- a/src/race.bat
+++ b/src/race.bat
@@ -36,6 +36,12 @@ go install -race cmd/cgo
echo # go install -race std
go install -race std
if errorlevel 1 goto fail
+:: we must unset GOROOT_FINAL before tests, because runtime/debug requires
+:: correct access to source code, so if we have GOROOT_FINAL in effect,
+:: at least runtime/debug test will fail.
+set GOROOT_FINAL=
+::
echo # go test -race -short std
go test -race -short std
if errorlevel 1 goto fail
コアとなるコードの解説
src/race.bash
の変更
src/race.bash
は、Unix系システム(Linux, macOSなど)でGoのレース検出器を有効にしたテストを実行するためのシェルスクリプトです。
追加された行:
# we must unset GOROOT_FINAL before tests, because runtime/debug requires
# correct access to source code, so if we have GOROOT_FINAL in effect,
# at least runtime/debug test will fail.
unset GOROOT_FINAL
この部分では、go test -race
コマンドを実行する直前に unset GOROOT_FINAL
というコマンドが追加されています。unset
はシェルコマンドで、指定された環境変数を現在のシェルセッションから削除します。これにより、以降のコマンド(go test
)は GOROOT_FINAL
の影響を受けなくなり、runtime/debug
がソースコードのパスを正しく解決できるようになります。コメントでその理由が明確に説明されています。
src/race.bat
の変更
src/race.bat
は、WindowsシステムでGoのレース検出器を有効にしたテストを実行するためのバッチスクリプトです。
追加された行:
:: we must unset GOROOT_FINAL before tests, because runtime/debug requires
:: correct access to source code, so if we have GOROOT_FINAL in effect,
:: at least runtime/debug test will fail.
set GOROOT_FINAL=
この部分では、go test -race
コマンドを実行する直前に set GOROOT_FINAL=
というコマンドが追加されています。Windowsのバッチスクリプトでは、set VARNAME=
とすることで、環境変数 VARNAME
の値を空に設定し、実質的にその環境変数を解除するのと同じ効果が得られます。これもまた、runtime/debug
のテストが正しく動作するようにするための措置であり、コメントでその意図が説明されています。
両方のスクリプトで同様のロジックが適用されており、クロスプラットフォームでのレース検出ビルドの信頼性向上に貢献しています。
関連リンク
- Go Issue 5537: https://github.com/golang/go/issues/5537 (このコミットメッセージで参照されているissue)
- Go Change-ID 98980043: https://golang.org/cl/98980043 (このコミットのChange List)
参考にした情報源リンク
- Goの公式ドキュメント (Go Race Detector): https://go.dev/doc/articles/race_detector
- Goの公式ドキュメント (runtime/debug): https://pkg.go.dev/runtime/debug
GOROOT_FINAL
に関するGoの議論や関連する変更履歴 (GitHub issues, Go mailing listsなど、特にGo 1.9およびGo 1.21での変更に関する情報)- https://github.com/golang/go/issues/60000 (Go 1.21での
GOROOT_FINAL
の削除に関する議論) - https://github.com/golang/go/issues/20000 (Go 1.9での
GOROOT
決定ロジックの変更に関する議論)
- https://github.com/golang/go/issues/60000 (Go 1.21での
- Web検索結果 (Google Search): "Go GOROOT_FINAL purpose runtime/debug 2014" などI have generated the detailed explanation in Markdown format, following all the user's instructions and the specified structure. I have included the commit information, background, prerequisite knowledge, technical details, core code changes, and relevant links. The output is now ready.
# [インデックス 19287] ファイルの概要
このコミットは、Go言語のテストスクリプトである `race.bash` と `race.bat` において、テスト実行前に環境変数 `GOROOT_FINAL` を解除する変更を導入します。これにより、特に `runtime/debug` パッケージのテストが `GOROOT_FINAL` の設定によって失敗する問題を解決し、Goのレース検出ビルドの信頼性を向上させます。
## コミット
commit 5d25189d801d7e8bf2fe10ffe95d43dda648a6b0 Author: Alex Brainman alex.brainman@gmail.com Date: Wed May 7 16:34:21 2014 +1000
race.bash,race.bat: unset GOROOT_FINAL during tests
Just like run.* scripts do.
Fixes race build.
LGTM=dave, dvyukov
R=dvyukov, dave
CC=golang-codereviews
https://golang.org/cl/98980043
## GitHub上でのコミットページへのリンク
[https://github.com/golang/go/commit/5d25189d801d7e8bf2fe10ffe95d43dda648a6b0](https://github.com/golang/go/commit/5d25189d801d7e8bf2fe10ffe95d43dda648a6b0)
## 元コミット内容
race.bash,race.bat: unset GOROOT_FINAL during tests
Just like run.* scripts do. Fixes race build.
LGTM=dave, dvyukov R=dvyukov, dave CC=golang-codereviews https://golang.org/cl/98980043
## 変更の背景
このコミットの背景には、Go言語のビルドシステムにおける `GOROOT_FINAL` 環境変数の挙動と、`runtime/debug` パッケージのテストの要件との間の不整合がありました。
Goのビルドプロセスでは、`GOROOT_FINAL` は、Goツールチェインがビルドされた場所とは異なる最終的なインストール場所を指定するために使用されることがありました。この変数が設定されていると、Goツール(`cmd/go` やその他のバイナリ)は、その値に基づいて自身の `GOROOT`(Goのインストールルート)を特定しようとします。これは、ビルド環境と実行環境が異なる場合に、ツールが正しく動作するために重要でした。
しかし、`runtime/debug` パッケージは、スタックトレースの生成など、実行時にソースコードのパスに正確にアクセスする必要があります。もし `GOROOT_FINAL` が設定されており、その値がテスト実行時の実際のソースコードの場所と一致しない場合、`runtime/debug` のテストがソースファイルを見つけられずに失敗するという問題が発生していました。
コミットメッセージにある「Just like run.* scripts do.」という記述は、Goの他のテスト実行スクリプト(`run.bash` など)では既に同様の問題を回避するために `GOROOT_FINAL` を解除する処理が行われていたことを示唆しています。このコミットは、レース検出器を有効にしたビルド(`go test -race`)を実行する `race.bash` および `race.bat` スクリプトにも同様の修正を適用することで、この不整合を解消し、レース検出ビルドの安定性を確保することを目的としています。
## 前提知識の解説
### GOROOTとGOROOT_FINAL
* **GOROOT**: Go言語のインストールディレクトリのルートパスを指す環境変数です。Goのツールチェイン(コンパイラ、リンカ、標準ライブラリなど)は、このパスを基準にファイルを探します。通常、Goをインストールすると自動的に設定されるか、ユーザーが手動で設定します。
* **GOROOT_FINAL**: Go 1.x系の初期の頃に存在した環境変数で、Goツールチェインをビルドした場所と、最終的にインストールして使用する場所が異なる場合に利用されました。`GOROOT_FINAL` が設定されていると、Goのバイナリ(`go` コマンドなど)は、この `GOROOT_FINAL` の値を自身の内部に埋め込み、実行時にその埋め込まれたパスを `GOROOT` として使用しようとしました。これにより、ビルド後にGoのインストールディレクトリを移動しても、ツールが正しく動作することが期待されました。しかし、このメカニズムは複雑さを増し、しばしば予期せぬ問題を引き起こす原因となりました。Go 1.9以降、`cmd/go` は `os.Executable` を使用して自身の場所を特定し、そこから `GOROOT` を導出するようになり、`GOROOT_FINAL` への依存度が低下しました。Go 1.21では、`GOROOT_FINAL` の明示的なサポートはGoのビルドシステムからほぼ削除されています。
### Goのレース検出器 (Race Detector)
Goには、並行処理におけるデータ競合(race condition)を検出するための組み込みのツールである「レース検出器」があります。これは、`go build -race` や `go test -race` のように `-race` フラグを付けてビルドまたはテストを実行することで有効になります。レース検出器は、実行時にメモリへのアクセスを監視し、複数のゴルーチンが同時に同じメモリ位置にアクセスし、少なくとも1つのアクセスが書き込みであり、かつそれらのアクセスが同期メカニズムによって保護されていない場合に警告を発します。これにより、デバッグが困難な並行処理のバグを早期に発見できます。
### runtime/debug パッケージ
`runtime/debug` パッケージは、Goプログラムのデバッグ情報にアクセスするための機能を提供します。主な機能には以下のようなものがあります。
* **スタックトレースの取得**: `runtime.Stack()` 関数は、現在のゴルーチンのスタックトレースをバイトスライスとして返します。このスタックトレースには、関数呼び出しの履歴、ファイル名、行番号などが含まれます。
* **ビルド情報の取得**: `runtime/debug.BuildInfo` 構造体を通じて、Goモジュールのパス、バージョン、ビルド時のGoバージョン、コンパイラフラグなどのビルド情報を取得できます。
* **GC情報の制御**: ガベージコレクションの動作に関する情報や制御を行う関数も提供します。
`runtime/debug` がスタックトレースを生成する際には、ソースコードのファイルパスと行番号を正確に参照する必要があります。
## 技術的詳細
このコミットが解決しようとしている技術的な問題は、`GOROOT_FINAL` が設定されている環境で `go test -race` を実行した際に、`runtime/debug` パッケージのテストが失敗するというものです。
具体的には、`runtime/debug` パッケージがスタックトレースを生成する際、またはその他のデバッグ情報を取得する際に、ソースコードのファイルパスを解決しようとします。もし `GOROOT_FINAL` が設定されており、その値がGoのソースコードが実際に存在するパスと異なる場合、`runtime/debug` は誤ったパスを検索したり、ソースファイルを見つけられなかったりする可能性があります。これにより、`runtime/debug` のテストが期待通りの結果を返せず、失敗に至ります。
`race.bash` と `race.bat` は、Goのレース検出器を有効にしたビルドとテストを実行するためのスクリプトです。これらのスクリプトが `go test -race std` を実行する前に `GOROOT_FINAL` を解除することで、`runtime/debug` パッケージは、Goツールチェインが現在実行されている環境(つまり、テストが実行されている実際のGoのインストール場所)に基づいてソースコードのパスを正しく解決できるようになります。これにより、`GOROOT_FINAL` の設定に起因するテストの失敗が回避され、レース検出ビルドのCI/CDパイプラインや開発環境での安定性が向上します。
この修正は、Goのビルドシステムにおける環境変数の取り扱いに関する一般的なプラクティス、すなわち、テストの実行においては可能な限りクリーンな環境を確保するという原則にも合致しています。
## コアとなるコードの変更箇所
### `src/race.bash`
```diff
--- a/src/race.bash
+++ b/src/race.bash
@@ -38,5 +38,11 @@ fi
# golang.org/issue/5537 - we must build a race enabled cmd/cgo before trying to use it.
go install -race cmd/cgo
go install -race std
+# we must unset GOROOT_FINAL before tests, because runtime/debug requires
+# correct access to source code, so if we have GOROOT_FINAL in effect,
+# at least runtime/debug test will fail.
+unset GOROOT_FINAL
+#
go test -race -short std
go test -race -run=nothingplease -bench=.* -benchtime=.1s -cpu=4 std
src/race.bat
--- a/src/race.bat
+++ b/src/race.bat
@@ -36,6 +36,12 @@ go install -race cmd/cgo
echo # go install -race std
go install -race std
if errorlevel 1 goto fail
+:: we must unset GOROOT_FINAL before tests, because runtime/debug requires
+:: correct access to source code, so if we have GOROOT_FINAL in effect,
+:: at least runtime/debug test will fail.
+set GOROOT_FINAL=
+::
echo # go test -race -short std
go test -race -short std
if errorlevel 1 goto fail
コアとなるコードの解説
src/race.bash
の変更
src/race.bash
は、Unix系システム(Linux, macOSなど)でGoのレース検出器を有効にしたテストを実行するためのシェルスクリプトです。
追加された行:
# we must unset GOROOT_FINAL before tests, because runtime/debug requires
# correct access to source code, so if we have GOROOT_FINAL in effect,
# at least runtime/debug test will fail.
unset GOROOT_FINAL
この部分では、go test -race
コマンドを実行する直前に unset GOROOT_FINAL
というコマンドが追加されています。unset
はシェルコマンドで、指定された環境変数を現在のシェルセッションから削除します。これにより、以降のコマンド(go test
)は GOROOT_FINAL
の影響を受けなくなり、runtime/debug
がソースコードのパスを正しく解決できるようになります。コメントでその理由が明確に説明されています。
src/race.bat
の変更
src/race.bat
は、WindowsシステムでGoのレース検出器を有効にしたテストを実行するためのバッチスクリプトです。
追加された行:
:: we must unset GOROOT_FINAL before tests, because runtime/debug requires
:: correct access to source code, so if we have GOROOT_FINAL in effect,
:: at least runtime/debug test will fail.
set GOROOT_FINAL=
この部分では、go test -race
コマンドを実行する直前に set GOROOT_FINAL=
というコマンドが追加されています。Windowsのバッチスクリプトでは、set VARNAME=
とすることで、環境変数 VARNAME
の値を空に設定し、実質的にその環境変数を解除するのと同じ効果が得られます。これもまた、runtime/debug
のテストが正しく動作するようにするための措置であり、コメントでその意図が説明されています。
両方のスクリプトで同様のロジックが適用されており、クロスプラットフォームでのレース検出ビルドの信頼性向上に貢献しています。
関連リンク
- Go Issue 5537: https://github.com/golang/go/issues/5537 (このコミットメッセージで参照されているissue)
- Go Change-ID 98980043: https://golang.org/cl/98980043 (このコミットのChange List)
参考にした情報源リンク
- Goの公式ドキュメント (Go Race Detector): https://go.dev/doc/articles/race_detector
- Goの公式ドキュメント (runtime/debug): https://pkg.go.dev/runtime/debug
GOROOT_FINAL
に関するGoの議論や関連する変更履歴 (GitHub issues, Go mailing listsなど、特にGo 1.9およびGo 1.21での変更に関する情報)- https://github.com/golang/go/issues/60000 (Go 1.21での
GOROOT_FINAL
の削除に関する議論) - https://github.com/golang/go/issues/20000 (Go 1.9での
GOROOT
決定ロジックの変更に関する議論)
- https://github.com/golang/go/issues/60000 (Go 1.21での
- Web検索結果 (Google Search): "Go GOROOT_FINAL purpose runtime/debug 2014" など