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

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

このコミットは、Go言語のテストスクリプト run.bat において、データ競合検出器(Race Detector)のテストを一時的に無効化する変更を加えています。これは、特定のバグ(Go issue 4948)が原因でテストが失敗するための一時的な回避策です。

コミット

commit 211589a9edf433019e8ad5937afe3bb98ebebc35
Author: Alex Brainman <alex.brainman@gmail.com>
Date:   Fri Mar 1 14:19:56 2013 +1100

    run.bat: disable race detector test
    
    R=golang-dev, dave
    CC=golang-dev
    https://golang.org/cl/7439048

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/211589a9edf433019e8ad5937afe3bb98ebebc35

元コミット内容

run.bat: disable race detector test

R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/7439048

変更の背景

このコミットの背景には、Go言語のデータ競合検出器(Race Detector)に関連する既知のバグが存在していました。コミットメッセージに記載されている http://code.google.com/p/go/issues/detail?id=4948 は、このバグを指しています。

Go言語の開発プロセスでは、継続的インテグレーション(CI)の一環として、様々なテストが自動的に実行されます。その中には、データ競合検出器を有効にした状態でのテストも含まれています。しかし、当時の特定の環境や条件下で、このデータ競合検出器のテストがバグにより正しく動作せず、失敗してしまう問題が発生していました。

テストの失敗は、CIパイプラインをブロックし、他の健全な変更の統合を妨げる可能性があります。そのため、このコミットは、根本的なバグが修正されるまでの間、一時的に問題のあるデータ競合検出器のテストをスキップすることで、CIパイプラインの健全性を維持することを目的としています。これは、開発の進行を妨げないための実用的な措置と言えます。

前提知識の解説

Go言語のデータ競合検出器 (Race Detector)

Go言語のデータ競合検出器は、並行処理における「データ競合(Data Race)」を検出するための強力なツールです。データ競合は、複数のゴルーチン(Goの軽量スレッド)が同時に同じメモリ領域にアクセスし、そのうち少なくとも1つが書き込み操作であり、かつそれらのアクセスが適切な同期メカニズムによって保護されていない場合に発生します。データ競合は、プログラムの予測不能な動作、クラッシュ、または誤った結果を引き起こす可能性があり、デバッグが非常に困難な種類のバグです。

Goのデータ競合検出器は、コンパイル時にメモリアクセスを計測(instrumentation)することで機能します。プログラムの実行中に、Goランタイムは共有変数への非同期アクセスを監視し、競合状態が検出されると警告を出力します。この警告には、競合が発生したゴルーチン、コードの行番号、および関連するスタックトレースなど、詳細な情報が含まれます。

データ競合検出器は、go test -racego run -racego build -race のように、go コマンドに -race フラグを付けて使用します。これにより、テスト実行時、プログラム実行時、またはバイナリビルド時にデータ競合の検出が有効になります。

ただし、データ競合検出器を有効にすると、実行時のオーバーヘッドが大きくなります。メモリ使用量が5〜10倍に増加し、実行時間が2〜20倍になることがあります。そのため、通常は開発およびテスト段階で使用され、本番環境では無効にされます。また、データ競合検出器は実行時に発生する競合のみを検出するため、テストカバレッジが重要になります。静的解析のように、実行されないコードパスの競合を検出することはできません。

run.bat スクリプト

run.bat は、Windows環境でGo言語のテストやビルドプロセスを実行するためのバッチスクリプトです。Go言語のプロジェクトでは、クロスプラットフォーム対応のために、シェルスクリプト(Linux/macOS向け)とバッチスクリプト(Windows向け)の両方が用意されていることがよくあります。このスクリプトは、Goのソースコードリポジトリのルートにある src ディレクトリに配置されており、Goのテストスイート全体を実行する役割を担っています。

スクリプト内では、go test コマンドが様々なフラグや引数と共に実行され、Goの標準ライブラリやツール群の機能が正しく動作するかどうかを検証します。データ競合検出器のテストも、このスクリプトの一部として実行されるように設定されていました。

Go Issue 4948

コミットメッセージに記載されている http://code.google.com/p/go/issues/detail?id=4948 は、Go言語の公式イシュートラッカー(当時はGoogle Codeでホストされていた)における特定のバグ報告を指します。Web検索の結果によると、このイシューはGo 1.13とApache Thriftの依存関係におけるチェックサム不一致の問題に関連している可能性が示唆されていますが、コミットが2013年であることから、これは別のイシューである可能性が高いです。

2013年当時のGo issue 4948は、データ競合検出器のテストが特定の条件下で誤って失敗する、またはハングアップするような問題であったと推測されます。このような問題は、テストインフラストラクチャの安定性を損ない、開発者が実際のバグとテストインフラのバグを区別するのを困難にします。そのため、一時的な回避策としてテストをスキップする判断が下されました。

技術的詳細

このコミットは、Windows環境におけるGo言語のテストスクリプト src/run.bat に変更を加えています。具体的には、データ競合検出器のテストセクションに、テストをスキップするためのロジックを追加しています。

run.bat スクリプトは、Goのテストを実行する際に、環境変数 GOHOSTOS, GOOS, GOARCH, CGO_ENABLED の値に基づいて、特定のテストセクションを実行するかどうかを判断しています。データ競合検出器のテストは、通常 windows-windows-amd64-1 の組み合わせ(つまり、Windows上でWindows AMD64向けにCGOが有効な場合)に限定されていました。これは、データ競合検出器がCGO(C言語との相互運用機能)を必要とし、特定のプラットフォームでのみサポートされていたためです。

変更前は、この条件が満たされると、go test -race コマンドが実行され、データ競合検出器を有効にした状態でテストが実行されていました。しかし、Go issue 4948で報告されたバグにより、このテストが不安定であったため、コミットでは以下の2行が追加されました。

  1. echo # skipping test due to bug (http://code.google.com/p/go/issues/detail?id=4948).

    • この行は、テストがスキップされる理由をコンソールに出力するためのコメントです。開発者やCIシステムが、なぜこのテストが実行されないのかを理解できるようにするためのものです。
  2. goto norace

    • この行は、バッチスクリプトの制御フローを変更するコマンドです。goto は指定されたラベル(この場合は norace)に処理をジャンプさせます。これにより、go test -race コマンドを含む後続のデータ競合検出器のテストコードが実行されずにスキップされます。norace ラベルは、データ競合検出器のテストセクションの終わり、またはそのセクションを完全にスキップするためのジャンプ先として、スクリプトの別の場所に定義されていると推測されます。

この変更により、Go issue 4948が修正されるまでの間、Windows AMD64環境でのデータ競合検出器のテストは実行されなくなり、CIパイプラインの安定性が確保されました。これは、バグの根本的な修正ではなく、一時的な回避策であり、バグが修正された後にはこの変更が元に戻されることが期待されます。

コアとなるコードの変更箇所

--- a/src/run.bat
+++ b/src/run.bat
@@ -54,6 +54,8 @@ echo.
 
 if not "%GOHOSTOS%-%GOOS%-%GOARCH%-%CGO_ENABLED%" == "windows-windows-amd64-1" goto norace
 echo # Testing race detector.
+echo # skipping test due to bug (http://code.google.com/p/go/issues/detail?id=4948).
+goto norace
 go test -race -i flag
 if errorlevel 1 goto fail
 go test -race -short flag

コアとなるコードの解説

変更は src/run.bat ファイルの54行目付近にあります。

元のコードでは、以下の条件文でデータ競合検出器のテストを実行するかどうかを判断していました。

if not "%GOHOSTOS%-%GOOS%-%GOARCH%-%CGO_ENABLED%" == "windows-windows-amd64-1" goto norace
echo # Testing race detector.
go test -race -i flag
if errorlevel 1 goto fail
go test -race -short flag

この条件文 if not "%GOHOSTOS%-%GOOS%-%GOARCH%-%CGO_ENABLED%" == "windows-windows-amd64-1" goto norace は、「もし現在の環境が windows-windows-amd64-1 でないならば、norace ラベルにジャンプしてデータ競合検出器のテストをスキップする」という意味です。つまり、このテストはWindows AMD64環境でCGOが有効な場合にのみ実行されるように設計されていました。

このコミットによって、この条件文が満たされ、データ競合検出器のテストが実行されるべきパスに入った直後に、以下の2行が追加されました。

echo # skipping test due to bug (http://code.google.com/p/go/issues/detail?id=4948).
goto norace
  1. echo # skipping test due to bug (http://code.google.com/p/go/issues/detail?id=4948).

    • これは単なるコメント行であり、echo コマンドによって標準出力にメッセージが表示されます。このメッセージは、なぜデータ競合検出器のテストがスキップされるのかを明確に示しています。
  2. goto norace

    • この行が変更の核心です。goto コマンドは、バッチスクリプトの実行フローを強制的に norace というラベルに移動させます。これにより、この goto コマンドの直後に続く go test -race -i flaggo test -race -short flag といった実際のデータ競合検出器のテストコマンドは実行されなくなります。

結果として、この変更は、特定のバグが修正されるまで、Windows AMD64環境におけるデータ競合検出器のテストを完全にバイパスする役割を果たします。これは、テストスイート全体の実行を妨げる不安定なテストを一時的に無効化するための、シンプルかつ効果的な方法です。

関連リンク

  • Go issue 4948 (当時のGoogle Codeのイシュートラッカー): http://code.google.com/p/go/issues/detail?id=4948 (現在のGoイシュートラッカーでは、古いイシューはGitHubに移行されているか、参照が変更されている可能性があります。Web検索結果では、Go 1.13とApache Thriftの関連イシューが示唆されていますが、コミット日付からすると別のイシューである可能性が高いです。)
  • Go CL 7439048: https://golang.org/cl/7439048 (GoのコードレビューシステムであるGerritの変更リストへのリンク)

参考にした情報源リンク