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

[インデックス 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キューの最大長)の値がこの固定値よりも大きい場合、テストの前提が崩れ、意図せずテストが失敗する可能性がありました。

具体的には、somaxconn150より大きい環境では、テストが期待するよりも多くの接続が確立されてしまい、ファイルディスクリプタのリークを検出するロジックが正しく機能しなくなることがありました。このコミットは、このテストの脆弱性を修正し、様々なシステム環境下でも安定して動作するように改善することを目的としています。

前提知識の解説

ファイルディスクリプタ (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の値は以下の要素に基づいて動的に決定されるようになります。

  1. listenerBacklog: これは、システムが許容するTCPリスナーのバックログキューのサイズを反映しています。これにより、テストがシステム固有のsomaxconn設定に適応できるようになります。
  2. 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コア数が多いシステムにおいても、ファイルディスクリプタのリークをより確実に検出できるようになりました。これは、テストの堅牢性と信頼性を大幅に向上させる重要な変更です。

関連リンク

参考にした情報源リンク