Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 19287] ファイルの概要

このコミットは、Go言語のテストスクリプトである race.bashrace.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/goos.Executable を使用して自身の場所を特定し、そこから GOROOT を導出するようになり、GOROOT_FINAL への依存度が低下しました。Go 1.21では、GOROOT_FINAL の明示的なサポートはGoのビルドシステムからほぼ削除されています。

Goのレース検出器 (Race Detector)

Goには、並行処理におけるデータ競合(race condition)を検出するための組み込みのツールである「レース検出器」があります。これは、go build -racego 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.bashrace.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の公式ドキュメント (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での変更に関する情報)
  • 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 のテストが正しく動作するようにするための措置であり、コメントでその意図が説明されています。

両方のスクリプトで同様のロジックが適用されており、クロスプラットフォームでのレース検出ビルドの信頼性向上に貢献しています。

関連リンク

参考にした情報源リンク