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

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

このコミットは、Go言語のビルドシステムにおけるPlan 9環境でのmake.rcスクリプトのバグ修正に関するものです。具体的には、rcシェルが--no-banner引数のチェック時に予期せず終了してしまう問題を解決し、all.rcスクリプトがrun.rcスクリプトを実行する前に終了してしまうのを防ぎます。

コミット

  • コミットハッシュ: ffe8a3c5e2996d3c017c5eb74e94515382b204a5
  • 作者: David du Colombier 0intro@gmail.com
  • 日付: Fri May 24 13:55:19 2013 -0700

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

https://github.com/golang/go/commit/ffe8a3c5e2996d3c017c5eb74e94515382b204a5

元コミット内容

build: fix make.rc on Plan 9

Set $status as null to prevent rc from exiting
on the last --no-banner argument checking when
used with rc -e. It allows all.rc to not exit
before executing run.rc

変更の背景

このコミットは、Plan 9オペレーティングシステム上でGo言語をビルドする際に発生していた問題を修正します。問題は、make.rcスクリプトがrcシェルで実行される際に、特定の条件下(特にrc -eオプションが使用されている場合)で、--no-banner引数のチェック後にrcシェルが予期せず終了してしまうことにありました。これにより、all.rcスクリプトがrun.rcスクリプトを正常に実行する前に処理が中断され、ビルドプロセスが失敗していました。この挙動は、rcシェルの$status変数の扱いに起因していました。

前提知識の解説

  • Plan 9 from Bell Labs: ベル研究所で開発された分散オペレーティングシステムです。Unixの哲学をさらに推し進め、すべてのリソースをファイルとして表現し、ネットワーク透過性を重視しています。Go言語の開発者の一部はPlan 9の設計思想に影響を受けており、GoのツールチェインにはPlan 9向けのビルドサポートが含まれています。
  • rcシェル: Plan 9の標準シェルであり、UnixのBourneシェル(sh)やCシェル(csh)とは異なる設計思想を持っています。rcはよりシンプルで一貫性のある構文を持ち、特にパイプライン処理や変数展開において特徴的な挙動を示します。
  • rc -eオプション: rcシェルでスクリプトを実行する際に、コマンドが非ゼロの終了ステータスを返した場合にシェルを即座に終了させるオプションです。これは、スクリプトの途中でエラーが発生した場合に、それ以降の処理を続行させないようにするために使用されます。
  • $status変数 (rcシェル): rcシェルにおける特殊変数の一つで、直前に実行されたコマンドの終了ステータスを保持します。Unix系のシェルにおける$?に相当しますが、rcでは$statusが空文字列(null)の場合に成功、非空文字列の場合に失敗と解釈されるという特徴があります。これは、Unixの終了コード(0が成功、非0が失敗)とは異なるセマンティクスです。

技術的詳細

rcシェルでは、コマンドの終了ステータスは$status変数に格納されます。Unix系のシェルとは異なり、rcでは$statusが空文字列('')であれば成功、非空文字列であれば失敗と判断されます。

問題が発生していたのは、src/make.rcスクリプト内で--no-banner引数のチェックが行われる部分でした。

if(! ~ $1 --no-banner)
	$GOTOOLDIR/dist banner

このif文の条件式! ~ $1 --no-bannerは、$1(スクリプトに渡された最初の引数)が--no-bannerと一致しない場合に真となります。この比較演算子~は、rcシェルではパターンマッチングを行います。

rc -eオプションが有効な場合、if文の条件式が評価された後、その結果に基づいて$status変数が設定されます。もしこの評価が何らかの理由で非空の$statusを設定してしまった場合、rc -eの挙動によりシェルがそこで終了してしまいます。

このコミットの修正は、if文の直後にstatus=''という行を追加することで、この問題を回避しています。これにより、if文の評価によって$statusが非空に設定されたとしても、その直後に明示的に$statusを空文字列にリセットすることで、rc -eによる予期せぬ終了を防ぎます。結果として、all.rcスクリプトは中断されることなくrun.rcスクリプトの実行に進むことができるようになります。

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

--- a/src/make.rc
+++ b/src/make.rc
@@ -95,3 +95,5 @@ rm -f $GOTOOLDIR/go_bootstrap
 
 if(! ~ $1 --no-banner)
 	$GOTOOLDIR/dist banner
+
+status=''

コアとなるコードの解説

追加された行は以下の通りです。

status=''

この行は、rcシェルにおいてstatusという変数を空文字列に設定しています。前述の通り、rcシェルでは$status変数が空文字列である場合に、直前のコマンドが成功したと解釈されます。

この修正は、if(! ~ $1 --no-banner)という条件式の評価後に、$status変数が意図せず非空の値になってしまう可能性があったため、それを明示的にリセットする目的で追加されました。これにより、rc -eオプションが有効な場合でも、この行が実行された時点で$statusが成功を示す状態に戻り、シェルが予期せず終了するのを防ぎます。

この変更は、GoのビルドプロセスがPlan 9環境で安定して動作するために不可欠なものでした。

関連リンク

参考にした情報源リンク