[インデックス 11890] ファイルの概要
コミット
このコミットは、Go言語の標準ライブラリ net/http パッケージ内のファイルシステム関連のテスト (fs_test.go) をより堅牢にするための変更です。具体的には、sendfile システムコールの検出ロジックを修正し、sendfile64 のようなバリアントも正しく認識できるようにしています。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/adb1a6ce3ca6b6f9c9aed7148cfc8b4b9b498b06
元コミット内容
commit adb1a6ce3ca6b6f9c9aed7148cfc8b4b9b498b06
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Tue Feb 14 17:11:12 2012 +1100
net/http: more robust test
Fixes #3014
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5665043
変更の背景
このコミットは、GoのIssue 3014を修正するために行われました。Issue 3014は、net/http パッケージの sendfile システムコールを使用するテストが、特定の環境(特に64ビット版の sendfile64 が使用される環境)で失敗する問題を報告していました。
sendfile は、ファイルディスクリプタ間でデータを直接転送するためのシステムコールで、ユーザー空間のバッファリングを介さずにカーネル空間でデータ転送を完結させることで、高いパフォーマンスを実現します。しかし、Linuxカーネルでは、ファイルサイズやオフセットが32ビットの範囲を超える場合に sendfile64 という別のシステムコールが提供されており、システムによっては sendfile の代わりに sendfile64 が内部的に呼び出されることがあります。
元のテストコードでは、strace コマンドの出力から sendfile システムコールの呼び出しを正規表現で検出していました。しかし、この正規表現が sendfile64 の呼び出しパターンを考慮していなかったため、sendfile64 が使用される環境ではテストが sendfile 呼び出しを検出できず、誤って失敗していました。このコミットは、この正規表現を修正することで、テストの堅牢性を向上させ、より多くの環境で正しく動作するようにすることを目的としています。
前提知識の解説
net/httpパッケージ: Go言語の標準ライブラリの一部で、HTTPクライアントとサーバーの実装を提供します。ウェブアプリケーションの構築やHTTP通信を行う際に広く利用されます。sendfileシステムコール: LinuxなどのUnix系OSで提供されるシステムコールの一つです。ファイルディスクリプタから別のファイルディスクリプタへデータを直接転送するために使用されます。特に、ファイルからネットワークソケットへのデータ転送において、ユーザー空間へのコピーを省略できるため、CPUオーバーヘッドを削減し、I/Oパフォーマンスを向上させることができます。sendfile64システムコール:sendfileと同様の機能を提供しますが、より大きなファイルサイズやオフセットを扱うために設計されています。32ビットシステムで大きなファイルを扱う場合や、64ビットシステムで明示的に64ビット版のインターフェースを使用する場合に利用されます。straceコマンド: Linuxで利用できるデバッグツールの一つで、プロセスが実行するシステムコールとそのシグナルをトレース(追跡)し、その詳細を表示します。プログラムがどのようなシステムコールを呼び出しているか、その引数や戻り値などを確認する際に非常に有用です。このテストでは、net/httpがsendfileを正しく利用しているかを確認するためにstraceの出力が解析されていました。- 正規表現 (Regular Expression): 文字列のパターンを記述するための強力なツールです。このコミットでは、
straceの出力から特定のシステムコール呼び出しパターンを検出するために正規表現が使用されています。\d+: 1つ以上の数字にマッチします。\s*: 0個以上の空白文字にマッチします。?: 直前の文字またはグループが0回または1回出現することにマッチします。例えば、sendfile(64)?はsendfileまたはsendfile64にマッチします。
技術的詳細
このコミットの技術的な核心は、net/http/fs_test.go 内の TestLinuxSendfile 関数における正規表現の修正です。このテストは、Linux環境で sendfile システムコールが正しく使用されていることを検証するために、strace コマンドの出力を解析していました。
元の正規表現は以下の通りでした。
rx := regexp.MustCompile(`sendfile\\(\\d+,\\s*\\d+,\\s*NULL,\\s*\\d+\\)\\s*=\\s*\\d+\\s*\\n`)
rxResume := regexp.MustCompile(`<\\.\\.\\. sendfile resumed> \\)\\s*=\\s*\\d+\\s*\\n`)
これらの正規表現は、sendfile(...) の形式に厳密にマッチするように設計されていました。しかし、一部のLinuxシステムや特定のコンパイルオプションでは、sendfile の代わりに sendfile64 が呼び出されることがあります。この場合、strace の出力には sendfile64(...) と表示されるため、元の正規表現ではこの呼び出しを検出できませんでした。
修正後の正規表現は以下の通りです。
rx := regexp.MustCompile(`sendfile(64)?\\(\\d+,\\s*\\d+,\\s*NULL,\\s*\\d+\\)\\s*=\\s*\\d+\\s*\\n`)
rxResume := regexp.MustCompile(`<\\.\\.\\. sendfile(64)? resumed> \\)\\s*=\\s*\\d+\\s*\\n`)
この変更では、sendfile の直後に (64)? が追加されています。
(と)はグループ化を示します。64はリテラルな文字列64にマッチします。?は直前のグループ (64) が0回または1回出現することを示します。
これにより、この正規表現は sendfile と sendfile64 の両方の文字列にマッチするようになり、テストがより広範な環境で sendfile システムコールの使用を正確に検出できるようになりました。この修正によって、特定の環境でのテストの誤検出が解消され、テストの信頼性が向上しました。
コアとなるコードの変更箇所
変更は src/pkg/net/http/fs_test.go ファイルの以下の行に集中しています。
--- a/src/pkg/net/http/fs_test.go
+++ b/src/pkg/net/http/fs_test.go
@@ -419,8 +419,8 @@ func TestLinuxSendfile(t *testing.T) {
child.Wait()
strace.Wait()
- rx := regexp.MustCompile(`sendfile\\(\\d+,\\s*\\d+,\\s*NULL,\\s*\\d+\\)\\s*=\\s*\\d+\\s*\\n`)
- rxResume := regexp.MustCompile(`<\\.\\.\\. sendfile resumed> \\)\\s*=\\s*\\d+\\s*\\n`)
+ rx := regexp.MustCompile(`sendfile(64)?\\(\\d+,\\s*\\d+,\\s*NULL,\\s*\\d+\\)\\s*=\\s*\\d+\\s*\\n`)
+ rxResume := regexp.MustCompile(`<\\.\\.\\. sendfile(64)? resumed> \\)\\s*=\\s*\\d+\\s*\\n`)
out := buf.String()
if !rx.MatchString(out) && !rxResume.MatchString(out) {
t.Errorf("no sendfile system call found in:\\n%s", out)
コアとなるコードの解説
TestLinuxSendfile 関数は、Goの net/http パッケージがLinuxの sendfile システムコールを適切に利用しているかを検証するためのテストです。このテストは、HTTPサーバーを起動し、ファイル転送を行い、その際に strace コマンドを使用してシステムコールの呼び出しを監視します。
変更された2行は、strace の出力から sendfile システムコールの呼び出しパターンを検出するための正規表現を定義しています。
rx変数は、sendfileの最初の呼び出しを検出するための正規表現です。rxResume変数は、sendfileが中断され、再開された場合のメッセージを検出するための正規表現です。
これらの正規表現に (64)? が追加されたことで、テストは sendfile と sendfile64 の両方のシステムコール名を認識できるようになりました。これにより、strace の出力に sendfile64 が現れた場合でも、テストはこれを有効な sendfile の使用として認識し、誤って失敗することがなくなります。
この修正は、テストのロバスト性(堅牢性)を高め、異なるLinux環境やカーネルバージョンでの互換性を向上させる上で重要です。
関連リンク
- Go Issue 3014:
net/http: TestLinuxSendfile fails on some systems(このコミットが修正した問題の報告) - Gerrit Change 5665043:
net/http: more robust test(このコミットに対応するGoのコードレビューシステムGerritのエントリ)
参考にした情報源リンク
sendfile(2)- Linux man page:sendfileシステムコールの詳細なドキュメントstrace(1)- Linux man page:straceコマンドの詳細なドキュメント- Go言語の
regexpパッケージのドキュメント: Goにおける正規表現の利用方法 - Go言語の
net/httpパッケージのドキュメント - Go言語のIssueトラッカー
- Go言語のGerritコードレビューシステム