[インデックス 11493] ファイルの概要
このコミットは、Go言語のランタイムにおけるmkasmh.sh
スクリプトの修正に関するものです。具体的には、trap
コマンドで使用されるシグナル名が、一部のシェル環境(特にDebianでデフォルトとして使用されるdash
シェル)で正しく解釈されない問題に対処しています。
コミット
commit 56e6a02490d27d5e4a98ba3c7f61f09b31a16aa2
Author: Russ Cox <rsc@golang.org>
Date: Mon Jan 30 23:17:11 2012 -0500
runtime: fix mkasmh.sh for arm?
The builder is Debian, so maybe running dash,
the shell that time forgot.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5600053
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/56e6a02490d27d5e4a98ba3c7f61f09b31a16aa2
元コミット内容
runtime: fix mkasmh.sh for arm?
The builder is Debian, so maybe running dash,
the shell that time forgot.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5600053
変更の背景
このコミットの背景には、Go言語のビルドシステムが直面していた特定の環境依存の問題があります。コミットメッセージにある「The builder is Debian, so maybe running dash, the shell that time forgot.」という記述がその核心を示しています。
Go言語のビルドプロセスでは、アセンブリコードのヘッダーファイルを生成するためにmkasmh.sh
のようなシェルスクリプトが使用されます。これらのスクリプトは、異なるオペレーティングシステムやアーキテクチャ(例: ARM)に対応するために、特定の環境変数を設定したり、一時ファイルを生成・削除したりする処理を含んでいます。
問題は、Goのビルド環境として使用されているDebianシステムにおいて、デフォルトのシェルがbash
ではなくdash
(Debian Almquist Shell)である可能性があったことです。dash
はbash
に比べて非常に軽量で高速ですが、POSIX標準に厳密に従う一方で、bash
が提供するような拡張機能や特定の挙動を持たないことがあります。
具体的には、trap
コマンドにおけるシグナル名の扱いに違いがありました。bash
ではSIGINT
やSIGTERM
といったシグナル名を直接指定できますが、dash
ではこれらのシグナル名が正しく認識されず、代わりにシグナル番号(例: SIGINT
は2
、SIGTERM
は15
)を使用する必要がある場合があります。
この不一致が原因で、mkasmh.sh
スクリプトがビルド中に予期せぬ終了(例えば、Ctrl+Cによる中断や外部からの終了シグナル)を受けた際に、一時ファイルが適切にクリーンアップされないという問題が発生していたと考えられます。これは、ビルドの失敗や、ビルド環境に不要なファイルが残る原因となり得ます。
このコミットは、このような環境依存のビルド問題を解決し、Goのビルドプロセスがより堅牢で、多様なLinuxディストリビューションで安定して動作するようにするための修正です。特にARMアーキテクチャ向けのビルドで問題が顕在化していた可能性が示唆されています。
前提知識の解説
1. シェルスクリプトとtrap
コマンド
シェルスクリプトは、Unix/Linuxシステムでタスクを自動化するために使用されるプログラムです。bash
やdash
などのシェルによって解釈・実行されます。
trap
コマンドは、シェルスクリプトが特定のシグナルを受信したときに実行するコマンドを指定するために使用されます。シグナルは、プロセスにイベントを通知するメカニズムであり、例えばユーザーがCtrl+Cを押したときに送信されるSIGINT
(Interrupt)や、プロセスを終了させるためのSIGTERM
(Terminate)などがあります。
trap
の一般的な構文は以下の通りです。
trap 'command_to_execute' SIGNAL1 SIGNAL2 ...
このコマンドは、SIGNAL1
やSIGNAL2
などのシグナルを受信した際に、指定されたcommand_to_execute
を実行するようにシェルに指示します。また、EXIT
という特別なシグナル(擬似シグナル)を指定すると、スクリプトが終了する直前に常に指定されたコマンドが実行されます。これは、一時ファイルのクリーンアップなど、スクリプトの終了時に必ず実行したい処理に非常に便利です。
2. シグナル名とシグナル番号
Unix/Linuxシステムでは、各シグナルには名前(例: SIGINT
, SIGTERM
, SIGHUP
など)と対応する番号(例: SIGINT
は2, SIGTERM
は15)が割り当てられています。
多くのシェル(特にbash
)では、trap
コマンドでシグナル名を使用できます。しかし、より古い、あるいはより軽量なシェル(例: dash
)では、シグナル名がサポートされていなかったり、特定のシグナル名が認識されなかったりする場合があります。このような場合、シグナル番号を使用することがより互換性の高い方法となります。
3. bash
とdash
シェルの違い
bash
(Bourne-Again SHell): 多くのLinuxディストリビューションでデフォルトの対話型シェルとして広く使用されています。豊富な機能、拡張性、ユーザーフレンドリーな機能(コマンド履歴、補完など)が特徴です。スクリプトにおいては、多くの便利な拡張機能を提供しますが、その分、POSIX標準から逸脱する挙動を示すこともあります。dash
(Debian Almquist Shell): DebianやUbuntuなどの一部のLinuxディストリビューションで、/bin/sh
のデフォルト実装として使用される軽量なシェルです。bash
に比べて起動が速く、メモリ使用量が少ないため、システム起動スクリプトや非対話型のスクリプトの実行に適しています。dash
はPOSIX標準に厳密に従うことを目指しており、bash
の拡張機能の多くはサポートしていません。この厳密さが、bash
で動作するスクリプトがdash
で問題を起こす原因となることがあります。
このコミットの文脈では、trap
コマンドにおけるシグナル名の解釈の違いが重要です。bash
ではSIGINT
やSIGTERM
が認識されますが、dash
ではこれらが認識されず、代わりにINT
やTERM
といった短縮形、あるいはシグナル番号を使用する必要があるという問題がありました。
4. Go言語のビルドシステムとクロスコンパイル
Go言語は、異なるオペレーティングシステムやCPUアーキテクチャ向けにバイナリを生成する「クロスコンパイル」を強力にサポートしています。この機能は、GOOS
(ターゲットOS)やGOARCH
(ターゲットアーキテクチャ)といった環境変数を設定することで利用できます。
Goのランタイム(runtime
パッケージ)は、アセンブリ言語で書かれた低レベルのコードを含んでおり、これらは特定のアーキテクチャに依存します。mkasmh.sh
のようなスクリプトは、これらのアセンブリコードがGoのビルドシステムによって正しく処理されるように、アーキテクチャ固有のヘッダーファイルを生成する役割を担っています。
ビルドシステムがDebian上で動作し、ARMアーキテクチャ向けのGoバイナリを生成する際に、dash
シェルのtrap
コマンドの挙動の違いが問題を引き起こしていたと考えられます。
技術的詳細
このコミットの技術的詳細は、シェルスクリプトのtrap
コマンドにおけるシグナルハンドリングの互換性問題に集約されます。
元のsrc/pkg/runtime/mkasmh.sh
スクリプトでは、一時ファイルのクリーンアップのためにtrap
コマンドが使用されていました。
trap "rm -f arch_GOARCH.h defs_GOOS_GOARCH.h os_GOOS.h signals_GOOS.h" EXIT SIGINT SIGTERM
この行は、スクリプトが終了する際(EXIT
)、またはSIGINT
シグナル(通常はCtrl+Cで発生)やSIGTERM
シグナル(プロセス終了要求)を受信した際に、指定されたrm -f ...
コマンドを実行して一時ファイルを削除するように設定しています。
問題は、Debianシステムでデフォルトの/bin/sh
がdash
シェルにリンクされている場合、dash
がSIGINT
やSIGTERM
といったシグナル名をそのままでは認識しないことにありました。dash
はPOSIX標準に厳密に従うため、シグナル名としてはINT
やTERM
といった短縮形、あるいはシグナル番号(SIGINT
は2、SIGTERM
は15)を期待します。
bash
ではSIGINT
やSIGTERM
が一般的に使用され、問題なく動作します。しかし、dash
環境でこのスクリプトが実行されると、SIGINT
やSIGTERM
に対するtrap
が正しく設定されず、スクリプトがこれらのシグナルによって中断された場合に、一時ファイルが削除されずに残ってしまう可能性がありました。
このコミットでは、この互換性の問題を解決するために、trap
コマンドのシグナル名をSIGINT
からINT
へ、SIGTERM
からTERM
へと変更しています。
-trap "rm -f arch_GOARCH.h defs_GOOS_GOARCH.h os_GOOS.h signals_GOOS.h" EXIT SIGINT SIGTERM
+trap "rm -f arch_GOARCH.h defs_GOOS_GOARCH.h os_GOOS.h signals_GOOS.h" EXIT INT TERM
この変更により、dash
シェルを含むより広範なPOSIX準拠シェル環境で、スクリプトがシグナルによって中断された場合でも、一時ファイルが確実にクリーンアップされるようになります。これは、Goのビルドプロセスの堅牢性を高め、異なるビルド環境での互換性を向上させるための重要な修正です。
特に、Goのビルドシステムはクロスコンパイルを多用するため、様々なOSやアーキテクチャの組み合わせでビルドスクリプトが実行される可能性があります。このような環境でシェルスクリプトの互換性を確保することは、ビルドの安定性にとって不可欠です。
コアとなるコードの変更箇所
diff --git a/src/pkg/runtime/mkasmh.sh b/src/pkg/runtime/mkasmh.sh
index eaabe07085..5eeff5065b 100755
--- a/src/pkg/runtime/mkasmh.sh
+++ b/src/pkg/runtime/mkasmh.sh
@@ -3,7 +3,7 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
-trap "rm -f arch_GOARCH.h defs_GOOS_GOARCH.h os_GOOS.h signals_GOOS.h" EXIT SIGINT SIGTERM
+trap "rm -f arch_GOARCH.h defs_GOOS_GOARCH.h os_GOOS.h signals_GOOS.h" EXIT INT TERM
set -e
SYS=$1
コアとなるコードの解説
変更はsrc/pkg/runtime/mkasmh.sh
ファイルの1行のみです。
元のコード:
trap "rm -f arch_GOARCH.h defs_GOOS_GOARCH.h os_GOOS.h signals_GOOS.h" EXIT SIGINT SIGTERM
変更後のコード:
trap "rm -f arch_GOARCH.h defs_GOOS_GOARCH.h os_GOOS.h signals_GOOS.h" EXIT INT TERM
この変更は、trap
コマンドに渡されるシグナル名のリストを修正しています。
EXIT
: これはシグナルではなく、スクリプトが正常終了するか、exit
コマンドで終了する直前に実行されることを意味します。この部分は変更されていません。SIGINT
からINT
へ:SIGINT
は、通常Ctrl+Cによって生成される割り込みシグナルです。bash
ではSIGINT
とINT
の両方が認識されますが、dash
のようなPOSIX準拠のシェルではINT
がより標準的で互換性のある形式です。SIGTERM
からTERM
へ:SIGTERM
は、プロセスに終了を要求するシグナルです。同様に、TERM
はdash
を含む多くのシェルで認識される標準的な形式です。
この修正により、mkasmh.sh
スクリプトがdash
シェル環境で実行された場合でも、INT
(割り込み)やTERM
(終了)シグナルを受信した際に、一時ファイル(arch_GOARCH.h
, defs_GOOS_GOARCH.h
, os_GOOS.h
, signals_GOOS.h
)が確実に削除されるようになります。これにより、ビルドプロセスの中断時におけるクリーンアップの信頼性が向上し、ビルド環境の整合性が保たれます。
関連リンク
- Go言語の公式リポジトリ: https://github.com/golang/go
- Go言語のコードレビューシステム (Gerrit): https://go.dev/cl/5600053 (コミットメッセージに記載されているCLリンク)
参考にした情報源リンク
trap
コマンドに関するドキュメント (例:man trap
またはオンラインのシェルスクリプトチュートリアル)bash
とdash
シェルの違いに関する情報 (例: Stack Overflow, Linuxドキュメント)- Unix/Linuxシグナルに関する情報 (例:
man 7 signal
またはオンラインのUnixプログラミングガイド) - Go言語のビルドシステムに関するドキュメント (Goの公式ドキュメントやソースコード)