[インデックス 14638] ファイルの概要
このコミットは、Go言語の標準ライブラリであるnet
パッケージ内のTestDialTimeoutFDLeak
テストの堅牢性を向上させることを目的としています。具体的には、システムの状態(特にsomaxconn
の値)によってテストが不安定になる問題を解決し、ファイルディスクリプタのリーク検出テストがより信頼性高く動作するように修正が加えられました。
コミット
commit feb509c794584d634ad1a51d88c0f6d109bf42d8
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Thu Dec 13 16:21:25 2012 +0900
net: make TestDialTimeoutFDLeak a bit robust
TestDialTimeoutFDLeak will fail when system state somaxconn is
greater than expected fixed value.
Fixes #4384 (again).
R=fullung, dave, rsc
CC=golang-dev
https://golang.org/cl/6873069
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/feb509c794584d634ad1a51d88c0f6d109bf42d8
元コミット内容
net: make TestDialTimeoutFDLeak a bit robust
TestDialTimeoutFDLeak will fail when system state somaxconn is
greater than expected fixed value.
Fixes #4384 (again).
R=fullung, dave, rsc
CC=golang-dev
https://golang.org/cl/6873069
変更の背景
TestDialTimeoutFDLeak
は、Goのnet
パッケージにおけるDialTimeout
関数が、タイムアウト時に適切にファイルディスクリプタ(FD)をクローズし、リークが発生しないことを検証するためのテストです。しかし、このテストは特定のシステム環境下で不安定になるという問題(Issue #4384)を抱えていました。
不安定さの主な原因は、テスト内で設定されていたmaxGoodConnect
という変数の値が固定値(150
)であったことです。この値は、テストが成功するために必要な「正常に接続できると期待されるコネクション数」を示していました。しかし、Linuxカーネルのネットワーク設定であるsomaxconn
(listenキューの最大長)の値がこの固定値よりも大きい場合、テストの前提が崩れ、意図せずテストが失敗する可能性がありました。
具体的には、somaxconn
が150
より大きい環境では、テストが期待するよりも多くの接続が確立されてしまい、ファイルディスクリプタのリークを検出するロジックが正しく機能しなくなることがありました。このコミットは、このテストの脆弱性を修正し、様々なシステム環境下でも安定して動作するように改善することを目的としています。
前提知識の解説
ファイルディスクリプタ (File Descriptor, FD)
ファイルディスクリプタは、Unix系オペレーティングシステムにおいて、ファイルやソケットなどのI/Oリソースを識別するために使用される抽象的なハンドルです。プログラムがファイルを開いたり、ネットワーク接続を確立したりするたびに、新しいファイルディスクリプタが割り当てられます。これらのFDは、使用後に適切にクローズされないと、システムリソースを消費し続け、最終的にはFDの枯渇(FD Leak)を引き起こし、新しい接続やファイルのオープンができなくなるなどの問題が発生します。
somaxconn
somaxconn
は、Linuxカーネルのネットワーク設定の一つで、TCPソケットのlisten()
システムコールにおけるバックログキューの最大長を定義します。バックログキューとは、サーバーがaccept()
システムコールで接続を受け入れる準備ができる前に、カーネルが一時的に保持できる保留中の接続の最大数です。
この値は/proc/sys/net/core/somaxconn
で確認・変更できます。デフォルト値はシステムによって異なりますが、通常は128や512などの値が設定されています。somaxconn
の値が大きいほど、サーバーはより多くの同時接続要求をキューに入れることができます。
listenerBacklog
Go言語のnet
パッケージにおいて、listenerBacklog
は、net.Listen
関数などで使用される、TCPリスナーのバックログキューのサイズを決定する内部的な値です。これは通常、システムが許容するsomaxconn
の値や、Goランタイムが内部的に決定する値に基づいています。この値は、サーバーが同時に処理できる接続要求の数を間接的に制御します。
runtime.NumCPU()
runtime.NumCPU()
は、Go言語のruntime
パッケージが提供する関数で、現在のシステムで利用可能な論理CPUの数を返します。この関数は、並行処理の最適化や、システムリソースに応じた処理の調整によく使用されます。例えば、ゴルーチンの数をCPUコア数に合わせることで、CPUバウンドなタスクのパフォーマンスを向上させることができます。
技術的詳細
このコミットの核心は、TestDialTimeoutFDLeak
テストにおけるmaxGoodConnect
変数の計算方法の変更です。以前は固定値150
が使用されていましたが、これはシステムごとのsomaxconn
の値に依存しないため、テストの信頼性を損なっていました。
新しい計算式は以下の通りです。
maxGoodConnect := listenerBacklog + runtime.NumCPU()*10
この変更により、maxGoodConnect
の値は以下の要素に基づいて動的に決定されるようになります。
listenerBacklog
: これは、システムが許容するTCPリスナーのバックログキューのサイズを反映しています。これにより、テストがシステム固有のsomaxconn
設定に適応できるようになります。runtime.NumCPU()*10
: システムの論理CPU数に10を掛けた値が加算されます。これは、テストが並行して多数の接続を試みる際に、CPUリソースの利用可能性を考慮に入れることで、テストの安定性をさらに高めるためのものです。CPU数が多いシステムでは、より多くの並行処理が可能であるため、テストもそれに応じてより多くの接続を試みることができます。
この動的な計算により、TestDialTimeoutFDLeak
は、様々なOSやハードウェア構成を持つ環境下でも、somaxconn
の値に左右されずに、ファイルディスクリプタのリークを正確に検出できるようになります。これにより、テストの信頼性が大幅に向上し、開発者がGoのネットワークコードの品質をより確実に検証できるようになります。
コアとなるコードの変更箇所
--- a/src/pkg/net/dial_test.go
+++ b/src/pkg/net/dial_test.go
@@ -241,7 +241,7 @@ func TestDialTimeoutFDLeak(t *testing.T) {
}\n \tdials := listenerBacklog + 100\n \t// used to be listenerBacklog + 5, but was found to be unreliable, issue 4384.\n-\tmaxGoodConnect := 150\n+\tmaxGoodConnect := listenerBacklog + runtime.NumCPU()*10\n \tresc := make(chan connErr)\n \tfor i := 0; i < dials; i++ {\n \t\tgo func() {\
コアとなるコードの解説
変更はsrc/pkg/net/dial_test.go
ファイル内のTestDialTimeoutFDLeak
関数にあります。
-
変更前:
maxGoodConnect := 150
この行では、maxGoodConnect
という変数が固定値150
で初期化されていました。これは、テストがタイムアウトする前に正常に確立されると期待される接続の最大数を表していました。しかし、前述の通り、この固定値がシステムごとのsomaxconn
設定と合致しない場合にテストの失敗を引き起こしていました。 -
変更後:
maxGoodConnect := listenerBacklog + runtime.NumCPU()*10
この行が修正され、maxGoodConnect
の値が動的に計算されるようになりました。listenerBacklog
: これは、Goの内部的なリスナーバックログのサイズを反映しており、間接的にシステムのsomaxconn
設定を考慮に入れます。runtime.NumCPU()*10
: システムの論理CPU数に10を掛けた値が加算されます。これにより、テストが並行して試みる接続の数が、システムの並行処理能力に合わせて調整されます。
この修正により、テストはより多くの接続を試行するようになり、特にsomaxconn
の値が大きいシステムや、CPUコア数が多いシステムにおいても、ファイルディスクリプタのリークをより確実に検出できるようになりました。これは、テストの堅牢性と信頼性を大幅に向上させる重要な変更です。
関連リンク
- Go Issue #4384: https://github.com/golang/go/issues/4384
- Go CL 6873069: https://golang.org/cl/6873069
参考にした情報源リンク
- Linux
somaxconn
documentation (e.g.,man 7 tcp
): https://man7.org/linux/man-pages/man7/tcp.7.html - Go
runtime
package documentation: https://pkg.go.dev/runtime - Go
net
package documentation: https://pkg.go.dev/net - ファイルディスクリプタに関する一般的な情報 (e.g., Wikipedia): https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%87%E3%82%A3%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%82%BF