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

[インデックス 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)である可能性があったことです。dashbashに比べて非常に軽量で高速ですが、POSIX標準に厳密に従う一方で、bashが提供するような拡張機能や特定の挙動を持たないことがあります。

具体的には、trapコマンドにおけるシグナル名の扱いに違いがありました。bashではSIGINTSIGTERMといったシグナル名を直接指定できますが、dashではこれらのシグナル名が正しく認識されず、代わりにシグナル番号(例: SIGINT2SIGTERM15)を使用する必要がある場合があります。

この不一致が原因で、mkasmh.shスクリプトがビルド中に予期せぬ終了(例えば、Ctrl+Cによる中断や外部からの終了シグナル)を受けた際に、一時ファイルが適切にクリーンアップされないという問題が発生していたと考えられます。これは、ビルドの失敗や、ビルド環境に不要なファイルが残る原因となり得ます。

このコミットは、このような環境依存のビルド問題を解決し、Goのビルドプロセスがより堅牢で、多様なLinuxディストリビューションで安定して動作するようにするための修正です。特にARMアーキテクチャ向けのビルドで問題が顕在化していた可能性が示唆されています。

前提知識の解説

1. シェルスクリプトとtrapコマンド

シェルスクリプトは、Unix/Linuxシステムでタスクを自動化するために使用されるプログラムです。bashdashなどのシェルによって解釈・実行されます。

trapコマンドは、シェルスクリプトが特定のシグナルを受信したときに実行するコマンドを指定するために使用されます。シグナルは、プロセスにイベントを通知するメカニズムであり、例えばユーザーがCtrl+Cを押したときに送信されるSIGINT(Interrupt)や、プロセスを終了させるためのSIGTERM(Terminate)などがあります。

trapの一般的な構文は以下の通りです。 trap 'command_to_execute' SIGNAL1 SIGNAL2 ...

このコマンドは、SIGNAL1SIGNAL2などのシグナルを受信した際に、指定されたcommand_to_executeを実行するようにシェルに指示します。また、EXITという特別なシグナル(擬似シグナル)を指定すると、スクリプトが終了する直前に常に指定されたコマンドが実行されます。これは、一時ファイルのクリーンアップなど、スクリプトの終了時に必ず実行したい処理に非常に便利です。

2. シグナル名とシグナル番号

Unix/Linuxシステムでは、各シグナルには名前(例: SIGINT, SIGTERM, SIGHUPなど)と対応する番号(例: SIGINTは2, SIGTERMは15)が割り当てられています。

多くのシェル(特にbash)では、trapコマンドでシグナル名を使用できます。しかし、より古い、あるいはより軽量なシェル(例: dash)では、シグナル名がサポートされていなかったり、特定のシグナル名が認識されなかったりする場合があります。このような場合、シグナル番号を使用することがより互換性の高い方法となります。

3. bashdashシェルの違い

  • bash (Bourne-Again SHell): 多くのLinuxディストリビューションでデフォルトの対話型シェルとして広く使用されています。豊富な機能、拡張性、ユーザーフレンドリーな機能(コマンド履歴、補完など)が特徴です。スクリプトにおいては、多くの便利な拡張機能を提供しますが、その分、POSIX標準から逸脱する挙動を示すこともあります。
  • dash (Debian Almquist Shell): DebianやUbuntuなどの一部のLinuxディストリビューションで、/bin/shのデフォルト実装として使用される軽量なシェルです。bashに比べて起動が速く、メモリ使用量が少ないため、システム起動スクリプトや非対話型のスクリプトの実行に適しています。dashはPOSIX標準に厳密に従うことを目指しており、bashの拡張機能の多くはサポートしていません。この厳密さが、bashで動作するスクリプトがdashで問題を起こす原因となることがあります。

このコミットの文脈では、trapコマンドにおけるシグナル名の解釈の違いが重要です。bashではSIGINTSIGTERMが認識されますが、dashではこれらが認識されず、代わりにINTTERMといった短縮形、あるいはシグナル番号を使用する必要があるという問題がありました。

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/shdashシェルにリンクされている場合、dashSIGINTSIGTERMといったシグナル名をそのままでは認識しないことにありました。dashはPOSIX標準に厳密に従うため、シグナル名としてはINTTERMといった短縮形、あるいはシグナル番号(SIGINTは2、SIGTERMは15)を期待します。

bashではSIGINTSIGTERMが一般的に使用され、問題なく動作します。しかし、dash環境でこのスクリプトが実行されると、SIGINTSIGTERMに対する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ではSIGINTINTの両方が認識されますが、dashのようなPOSIX準拠のシェルではINTがより標準的で互換性のある形式です。
  • SIGTERM から TERM: SIGTERMは、プロセスに終了を要求するシグナルです。同様に、TERMdashを含む多くのシェルで認識される標準的な形式です。

この修正により、mkasmh.shスクリプトがdashシェル環境で実行された場合でも、INT(割り込み)やTERM(終了)シグナルを受信した際に、一時ファイル(arch_GOARCH.h, defs_GOOS_GOARCH.h, os_GOOS.h, signals_GOOS.h)が確実に削除されるようになります。これにより、ビルドプロセスの中断時におけるクリーンアップの信頼性が向上し、ビルド環境の整合性が保たれます。

関連リンク

参考にした情報源リンク

  • trapコマンドに関するドキュメント (例: man trap またはオンラインのシェルスクリプトチュートリアル)
  • bashdashシェルの違いに関する情報 (例: Stack Overflow, Linuxドキュメント)
  • Unix/Linuxシグナルに関する情報 (例: man 7 signal またはオンラインのUnixプログラミングガイド)
  • Go言語のビルドシステムに関するドキュメント (Goの公式ドキュメントやソースコード)