[インデックス 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コードレビューシステム