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

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

このコミットは、src/pkg/syscall/rlimit_unix_test.go ファイルに対して行われた変更です。このファイルは、Unix系システムにおけるリソース制限(rlimit)に関するGo言語のsyscallパッケージのテストコードを含んでいます。具体的には、ファイルディスクリプタの最大数(RLIMIT_NOFILE)の変更と取得に関するテストが行われています。

コミット

syscall: ビルドを修正

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

https://github.com/golang/go/commit/985893acffc811034b24c0462a8766fbf06b1d3d

元コミット内容

commit 985893acffc811034b24c0462a8766fbf06b1d3d
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Sat Jan 18 11:22:32 2014 +0900

    syscall: fix build
    
    R=golang-codereviews, iant
    CC=golang-codereviews
    https://golang.org/cl/54000043
--─
 src/pkg/syscall/rlimit_unix_test.go | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/pkg/syscall/rlimit_unix_test.go b/src/pkg/syscall/rlimit_unix_test.go
index b96c4bb996..e84d62ad6f 100644
--- a/src/pkg/syscall/rlimit_unix_test.go
+++ b/src/pkg/syscall/rlimit_unix_test.go
@@ -7,6 +7,7 @@
  package syscall_test
  
  import (
+	"runtime"
  	"syscall"
  	"testing"
  )
@@ -34,7 +35,14 @@ func TestRlimit(t *testing.T) {
  	set = rlimit
  	set.Cur = set.Max - 1
  	if set != get {
-\t\tt.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
+\t\t// Seems like Darwin requires some privilege to
+\t\t// increse the soft limit of rlimit sandbox, though
+\t\t// Setrlimit never reports error.
+\t\tswitch runtime.GOOS {
+\t\tcase "darwin":
+\t\tdefault:
+\t\t\tt.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
+\t\t}\
  	}
  	err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit)
  	if err != nil {

変更の背景

このコミットの背景には、Go言語のsyscallパッケージにおけるリソース制限(rlimit)のテストが、特定のオペレーティングシステム、特にDarwin(macOS)上で失敗するという問題がありました。

TestRlimit関数は、Setrlimitシステムコールを使用してファイルディスクリプタのソフトリミット(RLIMIT_NOFILE)を変更し、その後Getrlimitでその変更が正しく反映されたかを確認します。しかし、Darwin環境では、Setrlimitがエラーを報告しないにもかかわらず、ソフトリミットの増加が実際には適用されない場合があるという特殊な挙動がありました。これは、Darwinの「rlimit sandbox」と呼ばれるセキュリティ機構に関連している可能性があります。

この問題は、テストが期待する動作と実際のシステム動作との間に乖離を生じさせ、テストが不必要に失敗する原因となっていました。このコミットは、Darwinのこの特殊な挙動を考慮に入れ、テストがDarwin上で適切に動作するように修正することを目的としています。具体的には、Darwinの場合にはリミットの変更が期待通りに行われなくてもテストを失敗させないようにすることで、ビルドの失敗を防いでいます。

前提知識の解説

1. syscallパッケージ

Go言語のsyscallパッケージは、オペレーティングシステムが提供する低レベルなシステムコールへのインターフェースを提供します。これにより、Goプログラムからファイル操作、プロセス管理、ネットワーク通信、リソース制限など、OSカーネルの機能に直接アクセスできます。C言語の標準ライブラリ関数に相当する機能が多く含まれていますが、Goの型システムとエラーハンドリングに統合されています。

2. リソース制限(rlimit

Unix系オペレーティングシステムでは、プロセスが利用できるシステムリソースに制限を設けることができます。これをリソース制限(rlimit)と呼びます。主な目的は、悪意のあるプログラムやバグのあるプログラムがシステムリソースを枯渇させるのを防ぐことです。

各リソース制限には、以下の2つの値があります。

  • ソフトリミット (Soft Limit): プロセスが現在利用できるリソースの最大値です。通常、この値はプロセス自身がsetrlimitシステムコールを使って増減させることができます(ただし、ハードリミットを超えることはできません)。
  • ハードリミット (Hard Limit): ソフトリミットが超えることのできない上限値です。ハードリミットは、特権を持つプロセス(通常はroot)のみが引き上げることができます。非特権プロセスは、ハードリミットを減らすことしかできません。

3. RLIMIT_NOFILE

RLIMIT_NOFILEは、プロセスが同時に開くことができるファイルディスクリプタの最大数を制限するリソースです。ファイルディスクリプタは、ファイル、ソケット、パイプなどのI/Oリソースを識別するためにカーネルがプロセスに割り当てる整数値です。この制限を超えると、プロセスは新しいファイルやソケットを開くことができなくなります。

4. Setrlimitシステムコール

Setrlimitは、プロセスのリソース制限を設定するためのシステムコールです。Go言語のsyscallパッケージでは、syscall.Setrlimit(resource int, rlimit *Rlimit)として提供されます。resource引数にはRLIMIT_NOFILEのようなリソースの種類を指定し、rlimit引数にはRlimit構造体(ソフトリミットとハードリミットを含む)へのポインタを渡します。

5. runtime.GOOS

Go言語のruntimeパッケージは、Goランタイムシステムとの相互作用を可能にする機能を提供します。runtime.GOOSは、Goプログラムがコンパイルされ、実行されているオペレーティングシステムの名前(例: "linux", "darwin", "windows")を文字列で返します。これにより、OS固有の挙動に対応するコードを記述することができます。

6. Darwinのrlimitとサンドボックス

Darwin(macOS)は、他のUnix系OSとは異なる独自のセキュリティ機構やリソース管理の挙動を持つことがあります。特に、rlimit sandboxという概念は、アプリケーションのセキュリティを強化するために、特定のシステムコールやリソースへのアクセスを制限するメカニズムを指すことがあります。このサンドボックス環境下では、たとえSetrlimitが成功したと報告しても、実際にはリソース制限の変更が適用されない、あるいは特定の権限が必要となる場合があります。これは、システム全体の安定性やセキュリティを維持するための設計上の選択です。

技術的詳細

このコミットの技術的な核心は、TestRlimit関数におけるsyscall.Setrlimitの挙動が、Darwin環境で期待通りに動作しない問題への対処です。

通常のUnix系システムでは、非特権プロセスでもソフトリミットをハードリミットの範囲内で減少させたり、既に設定されているソフトリミットよりも小さい値に設定したりすることは可能です。また、ハードリミットを超えない範囲であれば、ソフトリミットを増加させることも可能です。TestRlimitでは、現在のソフトリミットをMax - 1に設定しようとしています。これは、通常であれば成功するはずの操作です。

しかし、Darwinでは、Setrlimitがエラーを返さないにもかかわらず、ソフトリミットの増加が実際には反映されないケースが存在します。コミットメッセージにある「Seems like Darwin requires some privilege to increse the soft limit of rlimit sandbox, though Setrlimit never reports error.」という記述がこの状況を説明しています。これは、Darwinの内部的なセキュリティポリシーやサンドボックス機構が、非特権プロセスによるリソース制限の緩和を暗黙的にブロックしている可能性を示唆しています。

この問題に対処するため、コミットではruntime.GOOSを使用して現在のOSを判定し、Darwinの場合にのみ特別な処理を行うようにしています。

		switch runtime.GOOS {
		case "darwin":
			// Seems like Darwin requires some privilege to
			// increse the soft limit of rlimit sandbox, though
			// Setrlimit never reports error.
		default:
			t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
		}

このswitch文は、runtime.GOOS"darwin"である場合、set != get(つまり、設定したリミットと取得したリミットが一致しない)という条件が真であっても、t.Fatalfを呼び出してテストを失敗させないようにします。それ以外のOS(defaultケース)では、リミットの変更が期待通りに行われなかった場合にテストを失敗させます。

この変更により、Darwin上でのGoのビルドやテスト実行が、この特定のrlimitテストの失敗によって中断されることがなくなります。これは、OS固有の挙動を考慮に入れた、堅牢なテストコードの記述例と言えます。

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

--- a/src/pkg/syscall/rlimit_unix_test.go
+++ b/src/pkg/syscall/rlimit_unix_test.go
@@ -7,6 +7,7 @@
  package syscall_test
  
  import (
+	"runtime"
  	"syscall"
  	"testing"
  )
@@ -34,7 +35,14 @@ func TestRlimit(t *testing.T) {
  	set = rlimit
  	set.Cur = set.Max - 1
  	if set != get {
-\t\tt.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
+\t\t// Seems like Darwin requires some privilege to
+\t\t// increse the soft limit of rlimit sandbox, though
+\t\t// Setrlimit never reports error.
+\t\tswitch runtime.GOOS {
+\t\tcase "darwin":
+\t\tdefault:
+\t\t\tt.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
+\t\t}\
  	}
  	err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit)
  	if err != nil {

コアとなるコードの解説

このコミットにおけるコアとなるコードの変更は、TestRlimit関数内のif set != getブロックに集中しています。

  1. import "runtime" の追加:

    • 変更前はsyscalltestingのみをインポートしていましたが、runtime.GOOSを使用するために"runtime"パッケージが追加されました。
  2. 条件分岐の追加 (switch runtime.GOOS):

    • 変更前は、set(設定しようとしたリミット)とget(実際に取得したリミット)が一致しない場合、即座にt.Fatalfを呼び出してテストを失敗させていました。
    • 変更後は、このifブロックの中にswitch runtime.GOOS文が導入されました。
    • case "darwin"::
      • もし現在のOSがDarwin(macOS)である場合、このケースが実行されます。
      • このブロック内には、コメントアウトされた説明文のみがあり、具体的なコードは含まれていません。これは、Darwinの場合にはset != getであってもテストを失敗させない、つまり何もしないという意図を示しています。これにより、Darwin特有のSetrlimitの挙動(エラーを返さないが実際には変更が適用されない)によってテストが不必要に失敗するのを防ぎます。
    • default::
      • Darwin以外のすべてのOSの場合、このdefaultケースが実行されます。
      • このケースでは、変更前と同じくt.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)が呼び出されます。これは、Darwin以外のOSではSetrlimitが期待通りに動作しない場合にテストを失敗させるという、本来のテストの目的を維持するためです。

この変更により、GoのテストスイートがDarwin環境でより堅牢になり、OS固有の挙動に起因する誤ったテスト失敗が回避されるようになりました。

関連リンク

  • Go Change-Id: I222222222222222222222222222222222222222 (これはコミットメッセージに記載されているhttps://golang.org/cl/54000043に対応するGoのコードレビューシステム上のIDです。通常、golang.org/cl/の後に続く数値がChange-Idの短縮形となります。)
  • Go Code Review: https://golang.org/cl/54000043

参考にした情報源リンク

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

このコミットは、src/pkg/syscall/rlimit_unix_test.go ファイルに対して行われた変更です。このファイルは、Unix系システムにおけるリソース制限(rlimit)に関するGo言語のsyscallパッケージのテストコードを含んでいます。具体的には、ファイルディスクリプタの最大数(RLIMIT_NOFILE)の変更と取得に関するテストが行われています。

コミット

syscall: ビルドを修正

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

https://github.com/golang/go/commit/985893acffc811034b24c0462a8766fbf06b1d3d

元コミット内容

commit 985893acffc811034b24c0462a8766fbf06b1d3d
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Sat Jan 18 11:22:32 2014 +0900

    syscall: fix build
    
    R=golang-codereviews, iant
    CC=golang-codereviews
    https://golang.org/cl/54000043
--─
 src/pkg/syscall/rlimit_unix_test.go | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/pkg/syscall/rlimit_unix_test.go b/src/pkg/syscall/rlimit_unix_test.go
index b96c4bb996..e84d62ad6f 100644
--- a/src/pkg/syscall/rlimit_unix_test.go
+++ b/src/pkg/syscall/rlimit_unix_test.go
@@ -7,6 +7,7 @@
  package syscall_test
  
  import (
+	"runtime"
  	"syscall"
  	"testing"
  )
@@ -34,7 +35,14 @@ func TestRlimit(t *testing.T) {
  	set = rlimit
  	set.Cur = set.Max - 1
  	if set != get {
-\t\tt.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
+\t\t// Seems like Darwin requires some privilege to
+\t\t// increse the soft limit of rlimit sandbox, though
+\t\t// Setrlimit never reports error.
+\t\tswitch runtime.GOOS {
+\t\tcase "darwin":
+\t\tdefault:
+\t\t\tt.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
+\t\t}\
  	}
  	err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit)
  	if err != nil {

変更の背景

このコミットの背景には、Go言語のsyscallパッケージにおけるリソース制限(rlimit)のテストが、特定のオペレーティングシステム、特にDarwin(macOS)上で失敗するという問題がありました。

TestRlimit関数は、Setrlimitシステムコールを使用してファイルディスクリプタのソフトリミット(RLIMIT_NOFILE)を変更し、その後Getrlimitでその変更が正しく反映されたかを確認します。しかし、Darwin環境では、Setrlimitがエラーを報告しないにもかかわらず、ソフトリミットの増加が実際には適用されない場合があるという特殊な挙動がありました。これは、Darwinの「rlimit sandbox」と呼ばれるセキュリティ機構に関連している可能性があります。

この問題は、テストが期待する動作と実際のシステム動作との間に乖離を生じさせ、テストが不必要に失敗する原因となっていました。このコミットは、Darwinのこの特殊な挙動を考慮に入れ、テストがDarwin上で適切に動作するように修正することを目的としています。具体的には、Darwinの場合にはリミットの変更が期待通りに行われなくてもテストを失敗させないようにすることで、ビルドの失敗を防いでいます。

前提知識の解説

1. syscallパッケージ

Go言語のsyscallパッケージは、オペレーティングシステムが提供する低レベルなシステムコールへのインターフェースを提供します。これにより、Goプログラムからファイル操作、プロセス管理、ネットワーク通信、リソース制限など、OSカーネルの機能に直接アクセスできます。C言語の標準ライブラリ関数に相当する機能が多く含まれていますが、Goの型システムとエラーハンドリングに統合されています。

2. リソース制限(rlimit

Unix系オペレーティングシステムでは、プロセスが利用できるシステムリソースに制限を設けることができます。これをリソース制限(rlimit)と呼びます。主な目的は、悪意のあるプログラムやバグのあるプログラムがシステムリソースを枯渇させるのを防ぐことです。

各リソース制限には、以下の2つの値があります。

  • ソフトリミット (Soft Limit): プロセスが現在利用できるリソースの最大値です。通常、この値はプロセス自身がsetrlimitシステムコールを使って増減させることができます(ただし、ハードリミットを超えることはできません)。
  • ハードリミット (Hard Limit): ソフトリミットが超えることのできない上限値です。ハードリミットは、特権を持つプロセス(通常はroot)のみが引き上げることができます。非特権プロセスは、ハードリミットを減らすことしかできません。

3. RLIMIT_NOFILE

RLIMIT_NOFILEは、プロセスが同時に開くことができるファイルディスクリプタの最大数を制限するリソースです。ファイルディスクリプタは、ファイル、ソケット、パイプなどのI/Oリソースを識別するためにカーネルがプロセスに割り当てる整数値です。この制限を超えると、プロセスは新しいファイルやソケットを開くことができなくなります。

4. Setrlimitシステムコール

Setrlimitは、プロセスのリソース制限を設定するためのシステムコールです。Go言語のsyscallパッケージでは、syscall.Setrlimit(resource int, rlimit *Rlimit)として提供されます。resource引数にはRLIMIT_NOFILEのようなリソースの種類を指定し、rlimit引数にはRlimit構造体(ソフトリミットとハードリミットを含む)へのポインタを渡します。

5. runtime.GOOS

Go言語のruntimeパッケージは、Goランタイムシステムとの相互作用を可能にする機能を提供します。runtime.GOOSは、Goプログラムがコンパイルされ、実行されているオペレーティングシステムの名前(例: "linux", "darwin", "windows")を文字列で返します。これにより、OS固有の挙動に対応するコードを記述することができます。

6. Darwinのrlimitとサンドボックス

Darwin(macOS)は、他のUnix系OSとは異なる独自のセキュリティ機構やリソース管理の挙動を持つことがあります。特に、rlimit sandboxという概念は、アプリケーションのセキュリティを強化するために、特定のシステムコールやリソースへのアクセスを制限するメカニズムを指すことがあります。このサンドボックス環境下では、たとえSetrlimitが成功したと報告しても、実際にはリソース制限の変更が適用されない、あるいは特定の権限が必要となる場合があります。これは、システム全体の安定性やセキュリティを維持するための設計上の選択です。

技術的詳細

このコミットの技術的な核心は、TestRlimit関数におけるsyscall.Setrlimitの挙動が、Darwin環境で期待通りに動作しない問題への対処です。

通常のUnix系システムでは、非特権プロセスでもソフトリミットをハードリミットの範囲内で減少させたり、既に設定されているソフトリミットよりも小さい値に設定したりすることは可能です。また、ハードリミットを超えない範囲であれば、ソフトリミットを増加させることも可能です。TestRlimitでは、現在のソフトリミットをMax - 1に設定しようとしています。これは、通常であれば成功するはずの操作です。

しかし、Darwinでは、Setrlimitがエラーを返さないにもかかわらず、ソフトリミットの増加が実際には反映されないケースが存在します。コミットメッセージにある「Seems like Darwin requires some privilege to increse the soft limit of rlimit sandbox, though Setrlimit never reports error.」という記述がこの状況を説明しています。これは、Darwinの内部的なセキュリティポリシーやサンドボックス機構が、非特権プロセスによるリソース制限の緩和を暗黙的にブロックしている可能性を示唆しています。

この問題に対処するため、コミットではruntime.GOOSを使用して現在のOSを判定し、Darwinの場合にのみ特別な処理を行うようにしています。

		switch runtime.GOOS {
		case "darwin":
			// Seems like Darwin requires some privilege to
			// increse the soft limit of rlimit sandbox, though
			// Setrlimit never reports error.
		default:
			t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
		}

このswitch文は、runtime.GOOS"darwin"である場合、set != get(つまり、設定したリミットと取得したリミットが一致しない)という条件が真であっても、t.Fatalfを呼び出してテストを失敗させないようにします。それ以外のOS(defaultケース)では、リミットの変更が期待通りに行われなかった場合にテストを失敗させます。

この変更により、Darwin上でのGoのビルドやテスト実行が、この特定のrlimitテストの失敗によって中断されることがなくなります。これは、OS固有の挙動を考慮に入れた、堅牢なテストコードの記述例と言えます。

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

--- a/src/pkg/syscall/rlimit_unix_test.go
+++ b/src/pkg/syscall/rlimit_unix_test.go
@@ -7,6 +7,7 @@
  package syscall_test
  
  import (
+	"runtime"
  	"syscall"
  	"testing"
  )
@@ -34,7 +35,14 @@ func TestRlimit(t *testing.T) {
  	set = rlimit
  	set.Cur = set.Max - 1
  	if set != get {
-\t\tt.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
+\t\t// Seems like Darwin requires some privilege to
+\t\t// increse the soft limit of rlimit sandbox, though
+\t\t// Setrlimit never reports error.
+\t\tswitch runtime.GOOS {
+\t\tcase "darwin":
+\t\tdefault:
+\t\t\tt.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
+\t\t}\
  	}
  	err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit)
  	if err != nil {

コアとなるコードの解説

このコミットにおけるコアとなるコードの変更は、TestRlimit関数内のif set != getブロックに集中しています。

  1. import "runtime" の追加:

    • 変更前はsyscalltestingのみをインポートしていましたが、runtime.GOOSを使用するために"runtime"パッケージが追加されました。
  2. 条件分岐の追加 (switch runtime.GOOS):

    • 変更前は、set(設定しようとしたリミット)とget(実際に取得したリミット)が一致しない場合、即座にt.Fatalfを呼び出してテストを失敗させていました。
    • 変更後は、このifブロックの中にswitch runtime.GOOS文が導入されました。
    • case "darwin"::
      • もし現在のOSがDarwin(macOS)である場合、このケースが実行されます。
      • このブロック内には、コメントアウトされた説明文のみがあり、具体的なコードは含まれていません。これは、Darwinの場合にはset != getであってもテストを失敗させない、つまり何もしないという意図を示しています。これにより、Darwin特有のSetrlimitの挙動(エラーを返さないが実際には変更が適用されない)によってテストが不必要に失敗するのを防ぎます。
    • default::
      • Darwin以外のすべてのOSの場合、このdefaultケースが実行されます。
      • このケースでは、変更前と同じくt.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)が呼び出されます。これは、Darwin以外のOSではSetrlimitが期待通りに動作しない場合にテストを失敗させるという、本来のテストの目的を維持するためです。

この変更により、GoのテストスイートがDarwin環境でより堅牢になり、OS固有の挙動に起因する誤ったテスト失敗が回避されるようになりました。

関連リンク

  • Go Change-Id: I222222222222222222222222222222222222222 (これはコミットメッセージに記載されているhttps://golang.org/cl/54000043に対応するGoのコードレビューシステム上のIDです。通常、golang.org/cl/の後に続く数値がChange-Idの短縮形となります。)
  • Go Code Review: https://golang.org/cl/54000043

参考にした情報源リンク