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

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

このコミットは、Go言語プロジェクトのビルドスクリプトである src/run.bash 内のタイプミスを修正するものです。具体的には、ulimit コマンドを使用してデータセグメントサイズの上限を設定する際に、誤ってファイルディスクリプタ数の上限を設定するオプション (-n) が使われていた箇所を、正しいデータセグメントサイズの上限を設定するオプション (-d) に修正しています。この修正により、ビルドプロセスが正しくリソース制限を適用できるようになり、ビルドの失敗を防ぎます。

コミット

commit a1a414e6f12f759adde426a5bdd8985d0ee7067d
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Mon Sep 17 01:26:57 2012 +0800

    run.bash: fix a typo (fix build)
    
    R=golang-dev
    CC=golang-dev
    https://golang.org/cl/6506121

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

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

元コミット内容

run.bash: fix a typo (fix build)

R=golang-dev
CC=golang-dev
https://golang.org/cl/6506121

変更の背景

この変更は、Go言語のビルドシステムの一部である run.bash スクリプトにおけるタイプミスを修正するために行われました。run.bash は、Goのテストスイートやビルドプロセスを実行する際に、システムのリソース制限(ulimit)を設定するために使用されます。

問題となっていたのは、データセグメントサイズ(ulimit -d)の上限を設定しようとする行で、誤ってオープンファイルディスクリプタ数(ulimit -n)の上限を設定するオプションが使われていたことです。このタイプミスにより、スクリプトが意図したリソース制限を正しく適用できず、特定の環境下でのビルド失敗や予期せぬ動作を引き起こす可能性がありました。

このコミットは、このようなビルドの不安定性や誤ったリソース設定を解消し、run.bash スクリプトが意図通りに機能するようにするために必要とされました。

前提知識の解説

ulimit コマンド

ulimit は、Unix系オペレーティングシステムにおいて、ユーザーが利用できるシステムリソースの制限(リソースリミット)を表示または設定するためのシェル組み込みコマンドです。これらの制限は、プロセスが消費できるCPU時間、メモリ、ファイルサイズ、オープンできるファイルの数などを制御します。

ulimit コマンドには、以下のような主要なオプションがあります。

  • -H (Hard limit): ハードリミットを表示または設定します。ハードリミットは、スーパーユーザー(root)のみが引き上げることができ、一般ユーザーは引き下げることしかできません。
  • -S (Soft limit): ソフトリミットを表示または設定します。ソフトリミットは、ハードリミットを超えない範囲で、ユーザー自身が引き上げたり引き下げたりできます。プロセスはソフトリミットに達すると警告を受けますが、ハードリミットに達すると強制的に終了されることがあります。
  • -n (Number of open files): プロセスが同時にオープンできるファイルディスクリプタの最大数を指定します。
  • -d (Data segment size): プロセスのデータセグメントの最大サイズ(バイト単位)を指定します。データセグメントは、プログラムの初期化されたデータ、未初期化のデータ(BSS)、ヒープ領域などを含みます。
  • unlimited: 特定のリソースに対して制限を設けないことを意味します。

シェルスクリプトの条件分岐 [ ... ] || ...

このコミットで修正された行には、[ "$(ulimit -H -n)" == "unlimited" ] || ulimit -S -n $(ulimit -H -n) のような構造が見られます。これはシェルスクリプトにおける一般的な条件分岐のパターンです。

  • [ ... ]: これは test コマンドの短縮形であり、括弧内の条件式を評価します。
  • ==: 文字列の比較演算子です。
  • $(command): コマンド置換であり、command の実行結果を文字列として取得します。
  • || (OR): 論理OR演算子です。左側のコマンド([ ... ])が失敗した場合(終了ステータスが0以外の場合)にのみ、右側のコマンドが実行されます。

したがって、[ "$(ulimit -H -n)" == "unlimited" ] || ulimit -S -n $(ulimit -H -n) は、「もしハードリミットのオープンファイル数が unlimited でないならば、ソフトリミットのオープンファイル数をハードリミットの値に設定する」という意味になります。これは、リソース制限が既に無制限に設定されている場合は何もしないが、制限がある場合はソフトリミットをハードリミットまで引き上げる、という一般的なパターンです。

技術的詳細

修正された行は、src/run.bash スクリプト内で、Goのビルドやテスト実行に必要なリソース制限を適切に設定するために存在します。

元のコード: [ "$(ulimit -H -d)" == "unlimited" ] || ulimit -S -n $(ulimit -H -d)

この行の意図は、「データセグメントのハードリミットが unlimited でない場合、データセグメントのソフトリミットをハードリミットの値に設定する」ことでした。しかし、ulimit -S -n の部分で、データセグメント (-d) ではなく、オープンファイルディスクリプタ数 (-n) を設定しようとしていました。

結果として、このタイプミスは以下の問題を引き起こす可能性がありました。

  1. 意図しないリソース制限の適用: データセグメントのソフトリミットは変更されず、代わりにオープンファイルディスクリプタのソフトリミットが、データセグメントのハードリミットの値に設定されてしまう。これは、オープンファイルディスクリプタの制限が不適切に設定されることを意味します。
  2. ビルドの失敗: Goのビルドプロセスが大量のメモリ(データセグメント)を必要とする場合、データセグメントのソフトリミットが適切に引き上げられないために、メモリ不足エラーでビルドが失敗する可能性がありました。特に、We need at least 256 files and ~300 MB of bss. というコメントが示すように、bss (Block Started by Symbol) セグメント(未初期化データ)が約300MB必要とされており、これはデータセグメントの一部です。この制限が正しく設定されないと、ビルドが不安定になる原因となります。

修正後のコード: [ "$(ulimit -H -d)" == "unlimited" ] || ulimit -S -d $(ulimit -H -d)

この修正により、ulimit -S -d が正しく使用され、データセグメントのソフトリミットが意図通りにハードリミットの値に設定されるようになります。これにより、Goのビルドプロセスが十分なデータセグメント領域を確保できるようになり、ビルドの安定性が向上します。

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

変更は src/run.bash ファイルの1箇所のみです。

--- a/src/run.bash
+++ b/src/run.bash
@@ -18,7 +18,7 @@ ulimit -c 0
 # We need at least 256 files and ~300 MB of bss.
 # On OS X ulimit -S -n rejects 'unlimited'.
 [ "$(ulimit -H -n)" == "unlimited" ] || ulimit -S -n $(ulimit -H -n)
-[ "$(ulimit -H -d)" == "unlimited" ] || ulimit -S -n $(ulimit -H -d)
+[ "$(ulimit -H -d)" == "unlimited" ] || ulimit -S -d $(ulimit -H -d)
 
 # allow all.bash to avoid double-build of everything
 rebuild=true

具体的には、以下の行が変更されました。

- [ "$(ulimit -H -d)" == "unlimited" ] || ulimit -S -n $(ulimit -H -d) + [ "$(ulimit -H -d)" == "unlimited" ] || ulimit -S -d $(ulimit -H -d)

ulimit -S -n-n-d に修正されています。

コアとなるコードの解説

変更された行は、ulimit コマンドを使ってデータセグメントのソフトリミットを設定する部分です。

元のコードでは、ulimit -S -n $(ulimit -H -d) となっていました。

  • ulimit -H -d: データセグメントのハードリミットを取得します。
  • $(ulimit -H -d): 上記コマンドの出力(データセグメントのハードリミット値)を文字列として取得します。
  • ulimit -S -n ...: ここが問題の箇所で、取得したデータセグメントのハードリミット値を、オープンファイルディスクリプタ数 (-n) のソフトリミットとして設定しようとしていました。

修正後のコードでは、ulimit -S -d $(ulimit -H -d) となっています。

  • ulimit -S -d ...: データセグメント (-d) のソフトリミットを、データセグメントのハードリミット値に正しく設定します。

この修正により、スクリプトは意図通りにデータセグメントのソフトリミットを適切に引き上げることができ、Goのビルドプロセスが要求するメモリリソースを確保できるようになります。これは、特に大規模なビルドやテスト実行時に、リソース不足によるエラーを防ぐ上で重要です。

関連リンク

参考にした情報源リンク

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

このコミットは、Go言語プロジェクトのビルドスクリプトである src/run.bash 内のタイプミスを修正するものです。具体的には、ulimit コマンドを使用してデータセグメントサイズの上限を設定する際に、誤ってファイルディスクリプタ数の上限を設定するオプション (-n) が使われていた箇所を、正しいデータセグメントサイズの上限を設定するオプション (-d) に修正しています。この修正により、ビルドプロセスが正しくリソース制限を適用できるようになり、ビルドの失敗を防ぎます。

コミット

commit a1a414e6f12f759adde426a5bdd8985d0ee7067d
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Mon Sep 17 01:26:57 2012 +0800

    run.bash: fix a typo (fix build)
    
    R=golang-dev
    CC=golang-dev
    https://golang.org/cl/6506121

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

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

元コミット内容

run.bash: fix a typo (fix build)

R=golang-dev
CC=golang-dev
https://golang.org/cl/6506121

変更の背景

この変更は、Go言語のビルドシステムの一部である run.bash スクリプトにおけるタイプミスを修正するために行われました。run.bash は、Goのテストスイートやビルドプロセスを実行する際に、システムのリソース制限(ulimit)を設定するために使用されます。

問題となっていたのは、データセグメントサイズ(ulimit -d)の上限を設定しようとする行で、誤ってオープンファイルディスクリプタ数(ulimit -n)の上限を設定するオプションが使われていたことです。このタイプミスにより、スクリプトが意図したリソース制限を正しく適用できず、特定の環境下でのビルド失敗や予期せぬ動作を引き起こす可能性がありました。

このコミットは、このようなビルドの不安定性や誤ったリソース設定を解消し、run.bash スクリプトが意図通りに機能するようにするために必要とされました。

前提知識の解説

ulimit コマンド

ulimit は、Unix系オペレーティングシステムにおいて、ユーザーが利用できるシステムリソースの制限(リソースリミット)を表示または設定するためのシェル組み込みコマンドです。これらの制限は、プロセスが消費できるCPU時間、メモリ、ファイルサイズ、オープンできるファイルの数などを制御します。

ulimit コマンドには、以下のような主要なオプションがあります。

  • -H (Hard limit): ハードリミットを表示または設定します。ハードリミットは、スーパーユーザー(root)のみが引き上げることができ、一般ユーザーは引き下げることしかできません。
  • -S (Soft limit): ソフトリミットを表示または設定します。ソフトリミットは、ハードリミットを超えない範囲で、ユーザー自身が引き上げたり引き下げたりできます。プロセスはソフトリミットに達すると警告を受けますが、ハードリミットに達すると強制的に終了されることがあります。
  • -n (Number of open files): プロセスが同時にオープンできるファイルディスクリプタの最大数を指定します。
  • -d (Data segment size): プロセスのデータセグメントの最大サイズ(バイト単位)を指定します。データセグメントは、プログラムの初期化されたデータ、未初期化のデータ(BSS)、ヒープ領域などを含みます。
  • unlimited: 特定のリソースに対して制限を設けないことを意味します。

シェルスクリプトの条件分岐 [ ... ] || ...

このコミットで修正された行には、[ "$(ulimit -H -n)" == "unlimited" ] || ulimit -S -n $(ulimit -H -n) のような構造が見られます。これはシェルスクリプトにおける一般的な条件分岐のパターンです。

  • [ ... ]: これは test コマンドの短縮形であり、括弧内の条件式を評価します。
  • ==: 文字列の比較演算子です。
  • $(command): コマンド置換であり、command の実行結果を文字列として取得します。
  • || (OR): 論理OR演算子です。左側のコマンド([ ... ])が失敗した場合(終了ステータスが0以外の場合)にのみ、右側のコマンドが実行されます。

したがって、[ "$(ulimit -H -n)" == "unlimited" ] || ulimit -S -n $(ulimit -H -n) は、「もしハードリミットのオープンファイル数が unlimited でないならば、ソフトリミットのオープンファイル数をハードリミットの値に設定する」という意味になります。これは、リソース制限が既に無制限に設定されている場合は何もしないが、制限がある場合はソフトリミットをハードリミットまで引き上げる、という一般的なパターンです。

技術的詳細

修正された行は、src/run.bash スクリプト内で、Goのビルドやテスト実行に必要なリソース制限を適切に設定するために存在します。

元のコード: [ "$(ulimit -H -d)" == "unlimited" ] || ulimit -S -n $(ulimit -H -d)

この行の意図は、「データセグメントのハードリミットが unlimited でない場合、データセグメントのソフトリミットをハードリミットの値に設定する」ことでした。しかし、ulimit -S -n の部分で、データセグメント (-d) ではなく、オープンファイルディスクリプタ数 (-n) を設定しようとしていました。

結果として、このタイプミスは以下の問題を引き起こす可能性がありました。

  1. 意図しないリソース制限の適用: データセグメントのソフトリミットは変更されず、代わりにオープンファイルディスクリプタのソフトリミットが、データセグメントのハードリミットの値に設定されてしまう。これは、オープンファイルディスクリプタの制限が不適切に設定されることを意味します。
  2. ビルドの失敗: Goのビルドプロセスが大量のメモリ(データセグメント)を必要とする場合、データセグメントのソフトリミットが適切に引き上げられないために、メモリ不足エラーでビルドが失敗する可能性がありました。特に、We need at least 256 files and ~300 MB of bss. というコメントが示すように、bss (Block Started by Symbol) セグメント(未初期化データ)が約300MB必要とされており、これはデータセグメントの一部です。この制限が正しく設定されないと、ビルドが不安定になる原因となります。

修正後のコード: [ "$(ulimit -H -d)" == "unlimited" ] || ulimit -S -d $(ulimit -H -d)

この修正により、ulimit -S -d が正しく使用され、データセグメントのソフトリミットが意図通りにハードリミットの値に設定されるようになります。これにより、Goのビルドプロセスが十分なデータセグメント領域を確保できるようになり、ビルドの安定性が向上します。

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

変更は src/run.bash ファイルの1箇所のみです。

--- a/src/run.bash
+++ b/src/run.bash
@@ -18,7 +18,7 @@ ulimit -c 0
 # We need at least 256 files and ~300 MB of bss.
 # On OS X ulimit -S -n rejects 'unlimited'.
 [ "$(ulimit -H -n)" == "unlimited" ] || ulimit -S -n $(ulimit -H -n)
-[ "$(ulimit -H -d)" == "unlimited" ] || ulimit -S -n $(ulimit -H -d)
+[ "$(ulimit -H -d)" == "unlimited" ] || ulimit -S -d $(ulimit -H -d)
 
 # allow all.bash to avoid double-build of everything
 rebuild=true

具体的には、以下の行が変更されました。

- [ "$(ulimit -H -d)" == "unlimited" ] || ulimit -S -n $(ulimit -H -d) + [ "$(ulimit -H -d)" == "unlimited" ] || ulimit -S -d $(ulimit -H -d)

ulimit -S -n-n-d に修正されています。

コアとなるコードの解説

変更された行は、ulimit コマンドを使ってデータセグメントのソフトリミットを設定する部分です。

元のコードでは、ulimit -S -n $(ulimit -H -d) となっていました。

  • ulimit -H -d: データセグメントのハードリミットを取得します。
  • $(ulimit -H -d): 上記コマンドの出力(データセグメントのハードリミット値)を文字列として取得します。
  • ulimit -S -n ...: ここが問題の箇所で、取得したデータセグメントのハードリミット値を、オープンファイルディスクリプタ数 (-n) のソフトリミットとして設定しようとしていました。

修正後のコードでは、ulimit -S -d $(ulimit -H -d) となっています。

  • ulimit -S -d ...: データセグメント (-d) のソフトリミットを、データセグメントのハードリミット値に正しく設定します。

この修正により、スクリプトは意図通りにデータセグメントのソフトリミットを適切に引き上げることができ、Goのビルドプロセスが要求するメモリリソースを確保できるようになります。これは、特に大規模なビルドやテスト実行時に、リソース不足によるエラーを防ぐ上で重要です。

関連リンク

参考にした情報源リンク