[インデックス 11870] ファイルの概要
コミット
- コミットハッシュ:
569ef7d49e36048aeca92e387e934d5a53276949
- 作者: Russ Cox rsc@golang.org
- コミット日時: Mon Feb 13 22:23:04 2012 -0500
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/569ef7d49e36048aeca92e387e934d5a53276949
元コミット内容
net/http: disable buggy test
Generates an infinite stream (at least >1GB) of:
=== RUN TestTransportPersistConnLeak
2012/02/13 22:20:19 http: Accept error: accept tcp 127.0.0.1:63972:
too many open files
2012/02/13 22:20:19 http: Accept error: accept tcp 127.0.0.1:63972:
too many open files
... (以下同様のエラーが続く)
R=bradfitz
CC=golang-dev
https://golang.org/cl/5661052
変更の背景
このコミットは、Go言語の標準ライブラリであるnet/http
パッケージ内のテストTestTransportPersistConnLeak
が、バグによって無限に「too many open files」エラーを発生させ、大量のログ(1GB以上)を出力するという問題に対応するために行われました。このテストは、ファイルディスクリプタ(FD)のリークを引き起こしており、テスト実行環境のリソースを枯渇させる可能性がありました。
開発プロセスにおいて、テストが不安定であったり、予期せぬ副作用(この場合はリソースリーク)を引き起こしたりする場合、そのテストを一時的に無効化することは一般的な対応策です。これにより、CI/CDパイプラインの安定性を保ち、他の重要なテストの実行を妨げないようにします。このコミットは、根本的なバグ修正ではなく、問題のあるテストを一時的に隔離するための措置です。
前提知識の解説
- Go言語の
net/http
パッケージ: Go言語でHTTPクライアントおよびサーバーを実装するための標準ライブラリです。Webアプリケーション開発において中心的な役割を担います。 Transport
:net/http
パッケージにおけるTransport
インターフェースは、HTTPリクエストの送信とレスポンスの受信に関する低レベルの詳細を扱います。これには、接続の確立、プロキシの処理、TLSハンドシェイク、接続の再利用(永続接続)などが含まれます。http.DefaultTransport
は、デフォルトのTransport
実装であり、通常はHTTP/1.1の永続接続をサポートします。- 永続接続 (Persistent Connections / Keep-Alive): HTTP/1.1で導入された機能で、複数のHTTPリクエスト/レスポンスを単一のTCP接続上で送受信できるようにします。これにより、接続の確立と切断のオーバーヘッドが削減され、パフォーマンスが向上します。
- ファイルディスクリプタ (File Descriptors, FDs): オペレーティングシステムがファイルやソケットなどのI/Oリソースを識別するために使用する抽象的なハンドルです。プログラムがファイルを開いたり、ネットワーク接続を確立したりするたびに、FDが割り当てられます。システムには利用可能なFDの数に上限があり、これを使い果たすと「too many open files」エラーが発生します。
too many open files
エラー: プロセスがオペレーティングシステムから割り当てられるファイルディスクリプタの最大数を超過した際に発生するエラーです。これは、ファイルやネットワークソケットが適切に閉じられていない(リークしている)場合に頻繁に見られます。- Goのテストフレームワーク (
testing
パッケージ): Go言語には、標準でテストを記述するためのtesting
パッケージが用意されています。テスト関数はTest
で始まり、*testing.T
型の引数を取ります。 httptest.NewServer
:net/http/httptest
パッケージに含まれる関数で、テスト目的でHTTPサーバーを簡単に起動できます。実際のネットワークポートをリッスンし、テスト対象のHTTPクライアントからのリクエストを受け付けることができます。t.Logf
:*testing.T
型のメソッドで、テスト中にログメッセージを出力するために使用されます。fmt.Printf
と同様のフォーマット文字列をサポートします。return
文によるテストの無効化: Goのテスト関数内でreturn
文を使用すると、その時点以降のテストコードの実行が停止します。このコミットでは、テストの冒頭でreturn
することで、実質的にテスト全体を無効化しています。より慣用的なテストのスキップ方法としてはt.Skip()
がありますが、このコミットでは単純なreturn
が選択されています。
技術的詳細
このコミットで無効化されたTestTransportPersistConnLeak
テストは、net/http
パッケージのTransport
が永続接続を適切に管理し、リソース(特にファイルディスクリプタ)をリークしないことを検証することを目的としていたと考えられます。しかし、テスト自体にバグがあり、意図せずファイルディスクリプタのリークを引き起こしていました。
リークの症状は、テスト実行中に大量の「http: Accept error: accept tcp 127.0.0.1:63972: too many open files
」というエラーメッセージが無限に(または非常に大量に)出力されることでした。これは、テスト内でHTTPサーバーが多数の接続を確立しようとしているにもかかわらず、それらの接続に関連するファイルディスクリプタが適切に閉じられず、OSがプロセスに割り当てられるFDの上限に達してしまったことを示しています。結果として、新しい接続を受け入れることができなくなり、Accept error
が発生し続けていました。
この問題は、テストが実行されるたびにシステムリソースを消費し、テスト環境を不安定にするため、早急な対応が必要でした。根本原因の特定と修正には時間がかかる可能性があるため、一時的な措置として、テストを無効化することが選択されました。これにより、CIシステムや開発者のローカル環境でのテスト実行が妨げられることなく、他の開発作業を進めることが可能になります。
テストを無効化することは、そのテストがカバーしていた機能の回帰テストが行われなくなるというリスクを伴いますが、この場合はテスト自体がバグの原因となっていたため、一時的な無効化が最善の選択でした。
コアとなるコードの変更箇所
--- a/src/pkg/net/http/transport_test.go
+++ b/src/pkg/net/http/transport_test.go
@@ -635,6 +635,9 @@ func TestTransportGzipRecursive(t *testing.T) {
// tests that persistent goroutine connections shut down when no longer desired.
func TestTransportPersistConnLeak(t *testing.T) {
+\tt.Logf("test is buggy - appears to leak fds")
+\treturn
+\n
\tgotReqCh := make(chan bool)
\tunblockCh := make(chan bool)
\tts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
コアとなるコードの解説
変更はsrc/pkg/net/http/transport_test.go
ファイルのTestTransportPersistConnLeak
関数内で行われています。
-
t.Logf("test is buggy - appears to leak fds")
- この行は、テストが実行された際に、テストログに「test is buggy - appears to leak fds」(テストにバグがあり、ファイルディスクリプタをリークしているようです)というメッセージを出力します。これは、このテストが無効化された理由を明確にするためのものです。
t.Logf
は、Goのtesting
パッケージが提供するロギング機能で、テストの実行中に情報を出力する際に使用されます。
-
return
- この行が追加されたことで、
TestTransportPersistConnLeak
関数は、t.Logf
の呼び出し直後に実行を終了します。 - これにより、このテスト関数内の残りのコード(永続接続のリークをテストする本来のロジック)は一切実行されなくなります。
- 結果として、バグのあるテストが引き起こしていたファイルディスクリプタのリーク問題が回避されます。
- この行が追加されたことで、
この変更は、テストのロジック自体を修正するものではなく、単にその実行を停止させることで、問題の発生を防ぐための暫定的な措置です。
関連リンク
- Go CL 5661052: https://golang.org/cl/5661052 (このコミットに対応するGoのコードレビューシステム上のチェンジリスト)
参考にした情報源リンク
- Go言語公式ドキュメント:
net/http
パッケージ: https://pkg.go.dev/net/http - Go言語公式ドキュメント:
testing
パッケージ: https://pkg.go.dev/testing - Go言語公式ドキュメント:
net/http/httptest
パッケージ: https://pkg.go.dev/net/http/httptest - ファイルディスクリプタに関する一般的な情報 (例: Wikipedia, OSのドキュメントなど)
- HTTP永続接続 (Keep-Alive) に関する一般的な情報 (例: MDN Web Docs, RFCなど)