[インデックス 11139] ファイルの概要
このコミットは、Goプロジェクトのビルドプロセスにおいて、一時ファイルに固定されたファイル名を使用しないように変更するものです。これにより、特にMinGW環境におけるBashのバグを回避し、一時ファイルの衝突を防ぎます。
コミット
build: don't use a fixed filename in temp
Fixes #2688
R=golang-dev, gri, rsc
CC=golang-dev
https://golang.org/cl/5539050
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/630c83888622190f310a1c9748c676d76e127811
元コミット内容
このコミットは、ビルドシステムが一時ファイルを作成する際に、固定されたファイル名を使用している問題を修正します。具体的には、doc/progs/run
スクリプト内で定義されている一時ファイルパスが、すべてのユーザーやプロセスで共通の/tmp/gotest3
という固定名になっていました。この固定名が原因で、特にMinGW環境下のBashにおいて問題が発生していました。
変更の背景
この変更の背景には、#2688
として報告されたバグの修正があります。コミットメッセージには「Fixes #2688」と明記されており、Gerritの変更リスト(CL 5539050)のサマリーからも、このコミットが「issue 2688」を解決するものであることが確認できます。
具体的な問題は、「mingw bash bug」と記述されているように、MinGW(Minimalist GNU for Windows)環境でBashシェルを使用する際に発生する一時ファイルの衝突です。複数のユーザーが同じシステムで作業している場合や、同じユーザーが複数のプロセスで同時にスクリプトを実行している場合、固定された一時ファイル名を使用すると、ファイルへの同時書き込みや上書きが発生し、データの破損や予期せぬ動作を引き起こす可能性があります。特に、MinGWのBash環境では、このような競合状態が顕在化しやすかったと考えられます。
この問題は、ビルドやテストの実行中に不安定性をもたらす可能性があり、開発者の生産性やテストの信頼性に影響を与えていました。そのため、一時ファイルの命名規則を変更し、衝突を避けることが喫緊の課題となっていました。
前提知識の解説
- MinGW (Minimalist GNU for Windows): Windows上でUNIXライクな開発環境を提供するツールセットです。GCCコンパイラやBashシェルなど、GNUプロジェクトのツールをWindowsネイティブで実行できるようにします。Go言語の開発環境においても、WindowsユーザーがUNIXコマンドラインツールを利用する際によく使われます。
- 一時ファイル (Temporary File): プログラムが実行中に一時的にデータを保存するために作成するファイルです。通常、プログラムの終了時やシステムのリブート時に自動的に削除されるか、手動で削除されることが想定されています。
- 固定ファイル名 (Fixed Filename): 一時ファイルに常に同じ名前(例:
/tmp/data.tmp
)を使用することです。これは、複数のプロセスやユーザーが同時に同じファイルにアクセスしようとした場合に、競合状態(Race Condition)を引き起こす可能性があります。 - 競合状態 (Race Condition): 複数のプロセスやスレッドが共有リソース(この場合は一時ファイル)に同時にアクセスしようとしたときに、それらの操作の実行順序によって結果が非決定的に変わってしまう状態を指します。これにより、予期しないエラーやデータの破損が発生することがあります。
$USER
環境変数: UNIX系システムで一般的に使用される環境変数で、現在ログインしているユーザーの名前を格納しています。この変数をファイル名に含めることで、ユーザーごとに異なる一時ファイルパスを生成し、ユーザー間のファイル衝突を避けることができます。
技術的詳細
このコミットの技術的な核心は、一時ファイルの命名戦略の変更にあります。従来のdoc/progs/run
スクリプトでは、一時ファイルパスとして/tmp/gotest3
という絶対パスがハードコードされていました。これは、単一のユーザーが単一のプロセスでスクリプトを実行する場合には問題ありませんが、複数のユーザーが同じシステムで作業する場合や、同じユーザーが複数のシェルセッションでスクリプトを同時に実行する場合に、ファイル名の衝突を引き起こす可能性がありました。
特にMinGW環境下のBashでは、このような固定ファイル名が原因で、一時ファイルの作成やアクセスに関する特定のバグが顕在化していたと推測されます。このバグは、ファイルロックの不備、パーミッションの問題、あるいはBashのファイルI/O処理の特定の挙動に関連していた可能性があります。
この問題を解決するために、コミットは一時ファイル名に.$USER
というサフィックスを追加しました。これにより、TMPFILE
変数の値は/tmp/gotest3.$USER
となります。例えば、ユーザー名がjohn
であれば、一時ファイルは/tmp/gotest3.john
として作成されます。この変更により、各ユーザーは自分専用の一時ファイルを使用することになり、異なるユーザー間での一時ファイルの衝突が効果的に回避されます。
このアプローチは、同じユーザーが複数のプロセスでスクリプトを同時に実行する際の衝突を完全に防ぐものではありませんが(その場合は通常、プロセスID(PID)やランダムな文字列をファイル名に含めることがより堅牢な解決策となります)、特定の「mingw bash bug」がユーザー間の衝突に起因していたとすれば、この変更は問題の根本原因に対処し、安定性を向上させるための実用的な解決策となります。
コアとなるコードの変更箇所
変更はdoc/progs/run
ファイルの一箇所のみです。
--- a/doc/progs/run
+++ b/doc/progs/run
@@ -68,7 +68,7 @@ for i in \
done
# Write to temporary file to avoid mingw bash bug.
-TMPFILE="/tmp/gotest3"
+TMPFILE="/tmp/gotest3.$USER"
function testit {
$LD $1.$O
コアとなるコードの解説
変更された行は、TMPFILE
というシェル変数の定義です。
- 変更前:
TMPFILE="/tmp/gotest3"
- この行では、一時ファイルの名前が
/tmp/gotest3
という固定の文字列に設定されていました。これは、スクリプトが実行されるたびに同じパスのファイルを使用することを意味します。
- この行では、一時ファイルの名前が
- 変更後:
TMPFILE="/tmp/gotest3.$USER"
- この行では、一時ファイルの名前が
/tmp/gotest3
に加えて、現在のユーザー名を表す環境変数$USER
の値が追加されるように変更されました。例えば、ユーザー名がalice
であれば、一時ファイルは/tmp/gotest3.alice
となります。
- この行では、一時ファイルの名前が
このシンプルな変更により、異なるユーザーが同時にこのスクリプトを実行しても、それぞれが異なる一時ファイルを使用するようになります。これにより、一時ファイルの衝突が回避され、特にMinGW環境で報告されていたBashのバグが修正されます。この修正は、ビルドやテストの安定性を向上させる上で重要な役割を果たします。
関連リンク
- Gerrit Change-ID: https://golang.org/cl/5539050 - このコミットの元のコードレビューページです。レビューの議論や最終的な承認状況を確認できます。
- Go Issue 2688: このコミットが修正した具体的なバグ報告のリンクは、Goの公開Issueトラッカー上では直接見つかりませんでしたが、GerritのCLページで「issue 2688」として言及されています。これは、当時のGoプロジェクトのIssueトラッキングシステムにおける内部的な参照である可能性があります。
参考にした情報源リンク
- https://github.com/golang/go/commit/630c83888622190f310a1c9748c676d76e127811 - このコミットのGitHubページ
- https://golang.org/cl/5539050 - このコミットのGerritコードレビューページ
- MinGWに関する一般的な情報源 (例: Wikipedia, 公式ドキュメントなど)
- 一時ファイル、競合状態、環境変数に関する一般的なプログラミング知識