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

[インデックス 18492] ファイルの概要

このコミットは、Go言語の標準ライブラリであるnetパッケージ内のPlan 9オペレーティングシステム向けのホスト名ルックアップ処理に関するものです。具体的には、src/pkg/net/lookup_plan9.goファイルが変更されています。

コミット

commit 68bf5666cdc6805783be7c29fb2a634d8d45bc24
Author: Nicolas Owens <mischief@offblast.org>
Date:   Thu Feb 13 10:26:16 2014 -0500

    net: only return unique hosts during hostname lookup on plan 9
    
    TestLookupHost expects that no duplicate addresses are returned. when cs is consulted for a name, e.g net!localhost!1, it will possibly return multiple available paths, e.g. via il and tcp. this confuses the tests.
    
    LGTM=aram
    R=jas, 0intro, aram
    CC=golang-codereviews
    https://golang.org/cl/58120045

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/68bf5666cdc6805783be7c29fb2a634d8d45bc24

元コミット内容

net: only return unique hosts during hostname lookup on plan 9

TestLookupHost expects that no duplicate addresses are returned. when cs is consulted for a name, e.g net!localhost!1, it will possibly return multiple available paths, e.g. via il and tcp. this confuses the tests.

変更の背景

この変更の背景には、Go言語のnetパッケージにおけるホスト名ルックアップのテスト(TestLookupHost)が、重複するIPアドレスが返されないことを期待しているという問題がありました。しかし、Plan 9オペレーティングシステム上でホスト名を解決する際に、cs (connection server) が同じホスト名に対して複数の利用可能なパス(例えば、ilプロトコルとtcpプロトコル経由)を返すことがあり、これが重複したIPアドレスとしてテストに渡され、テストが失敗する原因となっていました。このコミットは、この問題を解決し、TestLookupHostの期待に沿うように、重複しないユニークなアドレスのみを返すように修正することを目的としています。

前提知識の解説

Plan 9オペレーティングシステム

Plan 9は、ベル研究所で開発された分散オペレーティングシステムです。その設計思想は、すべてのリソースをファイルとして扱い、ファイルシステムを通じてアクセスするというものです。ネットワーク通信も例外ではなく、/netファイルシステムを通じて行われます。

Plan 9のネットワークとcs (Connection Server)

Plan 9におけるネットワーク通信は、ファイルシステムを介して抽象化されています。ホスト名解決や接続確立の際には、cs (connection server) と呼ばれるユーザーレベルのプロセスが重要な役割を果たします。クライアントがシンボリックなホスト名をアドレスに解決する必要がある場合、/net/csにホスト名を書き込み、csプロセスがその名前を接続詳細に変換し、クライアントはそれを読み取ります。

il (Internet Layer) プロトコルとtcp (Transmission Control Protocol)

Plan 9は、独自のトランスポートプロトコルであるIL (Internet Layer) を持っています。これは、効率的なファイルシステムRPC (Remote Procedure Call) のために設計されています。TCPやUDPもサポートされていますが、Plan 9内部ではILが優先されることがあります。csがホスト名を解決する際、同じホスト名に対してIL経由のパスとTCP経由のパスの両方を返す可能性があり、これが重複アドレスの原因となります。

TestLookupHost

Go言語のnetパッケージには、ホスト名ルックアップ機能の正確性を検証するためのテストスイートが含まれています。TestLookupHostはその一部であり、ホスト名ルックアップの結果として返されるIPアドレスのリストが、重複を含まないユニークなものであることを期待しています。

技術的詳細

Plan 9のcsは、ホスト名解決時に、例えばnet!localhost!1のようなリクエストに対して、利用可能な複数のネットワークパスを返すことがあります。これは、同じ論理的なホスト名に対して、異なるプロトコル(iltcpなど)や異なるインターフェースを通じて到達可能な複数の経路が存在する場合に発生します。csはこれらの経路をすべて列挙するため、結果として同じIPアドレスが複数回リストに含まれる可能性があります。

GoのnetパッケージのlookupHost関数は、このcsからの応答を処理し、IPアドレスのリストを返します。しかし、TestLookupHostは、このリストに重複するIPアドレスが含まれていないことを前提としています。したがって、csが重複するアドレスを返すと、lookupHostがそれをそのまま返してしまい、テストが失敗するという問題が発生していました。

このコミットの目的は、lookupHost関数がPlan 9上で動作する際に、csから受け取ったアドレスリストから重複を排除し、ユニークなアドレスのみを返すようにすることです。これにより、TestLookupHostの期待を満たし、テストの安定性を確保します。

コアとなるコードの変更箇所

変更はsrc/pkg/net/lookup_plan9.goファイルに集中しています。

--- a/src/pkg/net/lookup_plan9.go
+++ b/src/pkg/net/lookup_plan9.go
@@ -123,6 +123,7 @@ func lookupHost(host string) (addrs []string, err error) {
 	if err != nil {
 		return
 	}
+loop:
 	for _, line := range lines {
 		f := getFields(line)
 		if len(f) < 2 {
@@ -135,6 +136,12 @@ func lookupHost(host string) (addrs []string, err error) {
 		if ParseIP(addr) == nil {
 			continue
 		}
+		// only return unique addresses
+		for _, a := range addrs {
+			if a == addr {
+				continue loop
+			}
+		}
 		addrs = append(addrs, addr)
 	}
 	return

コアとなるコードの解説

このコミットのコアとなる変更は、lookupHost関数内で、csから取得したアドレスをaddrsスライスに追加する前に、そのアドレスが既にスライス内に存在するかどうかを確認するロジックを追加した点です。

  1. loop: ラベルの追加: for _, line := range lines ループの直前に loop: というラベルが追加されました。これは、内側のループから外側のループの次のイテレーションに直接ジャンプするために使用されます。

  2. 重複チェックロジックの追加: 新しいアドレス addraddrs スライスに追加する直前に、以下のコードブロックが追加されました。

    		// only return unique addresses
    		for _, a := range addrs {
    			if a == addr {
    				continue loop
    			}
    		}
    

    このコードは、現在処理しているアドレス addr が、既に addrs スライスに格納されているいずれかのアドレス a と一致するかどうかをチェックします。

    • もし一致するアドレスが見つかった場合(つまり、addrが重複している場合)、continue loopが実行されます。これにより、内側のforループを抜け、外側のfor _, line := range linesループの次のイテレーションに直接進みます。結果として、重複するアドレスはaddrsスライスに追加されません。
    • 一致するアドレスが見つからなかった場合(つまり、addrがユニークな場合)、ループは最後まで実行され、addrs = append(addrs, addr)によってaddrがスライスに追加されます。

この変更により、lookupHost関数は、Plan 9のcsが重複するアドレスを返した場合でも、最終的にTestLookupHostが期待するようなユニークなIPアドレスのリストのみを返すようになります。

関連リンク

参考にした情報源リンク