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

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

このコミットは、Go言語のnetパッケージにおけるWindowsビルドの修正を目的としています。具体的には、SO_BROADCASTソケットオプションの設定結果を無視するように変更し、また、setIPv4MulticastInterfaceがWindowsで実装されていないために失敗するTestSimpleListenMulticastUDPテストを無効化しています。これにより、Windows環境でのGoのネットワーク機能の安定性とビルドの成功を確保しています。

コミット

commit 238af7700e6e61d75b108d8d67e354b3b2c49aee
Author: Alex Brainman <alex.brainman@gmail.com>
Date:   Wed Feb 1 12:13:46 2012 +1100

    net: fix windows build
    
    Ignore result of setting SO_BROADCAST.
    
    Disable TestSimpleListenMulticastUDP as
    setIPv4MulticastInterface is not implemented.
    
    R=golang-dev, bradfitz, mikioh.mikioh
    CC=golang-dev
    https://golang.org/cl/5610044
---
 src/pkg/net/multicast_test.go  | 2 +-\
 src/pkg/net/sockopt_windows.go | 6 +-----\
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/src/pkg/net/multicast_test.go b/src/pkg/net/multicast_test.go
index bf0fe4d8d0..4112f47cb2 100644
--- a/src/pkg/net/multicast_test.go
+++ b/src/pkg/net/multicast_test.go
@@ -86,7 +86,7 @@ func TestListenMulticastUDP(t *testing.T) {
 
 func TestSimpleListenMulticastUDP(t *testing.T) {
 	switch runtime.GOOS {
-	case "plan9":
+	case "plan9", "windows":
 		return
 	}
 
diff --git a/src/pkg/net/sockopt_windows.go b/src/pkg/net/sockopt_windows.go
index 2b861de30b..842bccc8f4 100644
--- a/src/pkg/net/sockopt_windows.go
+++ b/src/pkg/net/sockopt_windows.go
@@ -27,11 +27,7 @@ func setDefaultSockopts(s syscall.Handle, f, t int) error {
 	// to be handled by the correct socket.
 
 	// Allow broadcast.
-\terr := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)\n-\tif err != nil {\n-\t\treturn os.NewSyscallError(\"setsockopt\", err)\n-\t}\n-\n+\tsyscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)\n \treturn nil
 }\n 

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

https://github.com/golang/go/commit/238af7700e6e61d75b108d8d67e354b3b2c49aee

元コミット内容

commit 238af7700e6e61d75b108d8d67e354b3b2c49aee
Author: Alex Brainman <alex.brainman@gmail.com>
Date:   Wed Feb 1 12:13:46 2012 +1100

    net: fix windows build
    
    Ignore result of setting SO_BROADCAST.
    
    Disable TestSimpleListenMulticastUDP as
    setIPv4MulticastInterface is not implemented.
    
    R=golang-dev, bradfitz, mikioh.mikioh
    CC=golang-dev
    https://golang.org/cl/5610044
---\n src/pkg/net/multicast_test.go  | 2 +-\
 src/pkg/net/sockopt_windows.go | 6 +-----\
 2 files changed, 2 insertions(+), 6 deletions(-)

変更の背景

このコミットは、Go言語のnetパッケージがWindows環境で適切に動作し、ビルドが成功するようにするための修正です。主な問題点は以下の2つでした。

  1. SO_BROADCASTソケットオプション設定時のエラーハンドリング: Windows環境において、syscall.SetsockoptInt関数を用いてSO_BROADCASTオプションを設定する際に、エラーが発生する可能性がありました。しかし、このエラーは必ずしも致命的なものではなく、場合によっては無視しても問題ないケースがありました。以前の実装では、このエラーが発生すると処理が中断されてしまい、Windowsでのネットワーク機能の利用に支障をきたしていました。このコミットでは、このエラーを無視することで、より堅牢な動作を目指しています。

  2. マルチキャストUDPテストのWindowsでの失敗: TestSimpleListenMulticastUDPというテストは、マルチキャストUDP通信の基本的な機能を検証するためのものです。このテストは、内部的にsetIPv4MulticastInterfaceという関数に依存しています。しかし、当時のGoのWindows実装では、このsetIPv4MulticastInterfaceがまだ実装されていませんでした。そのため、Windows上でこのテストを実行すると、未実装の関数を呼び出そうとしてテストが失敗していました。このコミットでは、Windows環境ではこのテストをスキップすることで、テストスイート全体の安定性を確保しています。

これらの問題は、Go言語が様々なプラットフォームで動作することを目指す上で、特にWindowsのようなOS固有の挙動に対応する必要があることを示しています。

前提知識の解説

このコミットを理解するためには、以下の技術的な概念を把握しておく必要があります。

  • Go言語のnetパッケージ: Go言語の標準ライブラリの一部であり、ネットワークプログラミングのための基本的な機能を提供します。TCP/IP、UDP、Unixドメインソケットなど、様々なネットワークプロトコルを扱うことができます。ソケットの作成、接続、データの送受信、リスニングなどの機能が含まれます。

  • ソケットオプション (setsockopt): オペレーティングシステムが提供するソケットAPIの一部で、ソケットの挙動を制御するための様々なオプションを設定するために使用されます。setsockopt関数(Goではsyscall.SetsockoptIntなど)を通じて、ソケットのバッファサイズ、タイムアウト、ブロードキャストの許可など、低レベルな設定を変更できます。

  • SO_BROADCAST: ソケットオプションの一つで、ソケットがブロードキャストメッセージを送受信できるようにするかどうかを制御します。ブロードキャストとは、ネットワーク上の全てのデバイスにデータを送信する通信方式です。通常、UDPソケットでブロードキャスト通信を行う場合にこのオプションを有効にします。

  • syscallパッケージ: Go言語の標準ライブラリの一部で、オペレーティングシステムの低レベルなシステムコールにアクセスするための機能を提供します。これにより、GoプログラムからOS固有のAPI(例えば、ソケットオプションの設定など)を直接呼び出すことができます。

  • マルチキャストUDP: UDP(User Datagram Protocol)通信の一種で、特定のグループに属する複数の受信者に対して、単一の送信元からデータを効率的に送信する通信方式です。ブロードキャストとは異なり、マルチキャストは特定のグループにのみデータを送信するため、ネットワークの負荷を軽減できます。マルチキャスト通信では、特定のマルチキャストグループアドレスに参加(join)する必要があります。

  • runtime.GOOS: Go言語の組み込み変数で、プログラムが実行されているオペレーティングシステムの名前(例: "linux", "windows", "darwin", "plan9"など)を文字列で返します。これにより、Goプログラムは実行環境に応じて異なるコードパスを選択することができます。これはクロスプラットフォーム開発において非常に重要な機能です。

  • setIPv4MulticastInterface: IPv4マルチキャスト通信において、どのネットワークインターフェースを使用してマルチキャストパケットを送受信するかを設定するための関数(またはそれに相当する機能)です。マルチキャスト通信では、複数のネットワークインターフェースを持つシステムで、適切なインターフェースを選択することが重要になります。

技術的詳細

このコミットの技術的詳細は、Go言語のクロスプラットフォーム対応と、OS固有のネットワークAPIの挙動への対応に焦点を当てています。

  1. SO_BROADCAST設定のエラー無視:

    • src/pkg/net/sockopt_windows.goファイルでは、setDefaultSockopts関数内でSO_BROADCASTオプションを設定しています。
    • 以前のコードでは、syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)の呼び出し結果をerr変数で受け取り、if err != nilでエラーチェックを行っていました。エラーが発生した場合はos.NewSyscallErrorを返していました。
    • この変更では、err := ...if err != nilのブロックが削除され、syscall.SetsockoptIntの呼び出し結果が直接無視されるようになりました。
    • この変更の背景には、Windowsの特定のバージョンやネットワーク構成において、SO_BROADCASTの設定が常に成功するとは限らない、あるいは成功しなくてもブロードキャスト機能自体は問題なく動作する場合がある、という実情があったと考えられます。例えば、一部の仮想環境や特定のネットワークアダプタでは、この設定がエラーを返すことがあっても、それがアプリケーションの動作に致命的な影響を与えないケースが存在します。Goの設計思想として、可能な限り多くの環境で動作することを目指しているため、このような非致命的なエラーは無視する判断がなされたと推測されます。これにより、Windows環境でのGoのネットワークアプリケーションの互換性と安定性が向上します。
  2. TestSimpleListenMulticastUDPのWindowsでのスキップ:

    • src/pkg/net/multicast_test.goファイルには、マルチキャストUDP通信をテストするTestSimpleListenMulticastUDP関数があります。
    • このテストは、switch runtime.GOOS文を使用して、特定のOSではテストをスキップするロジックを含んでいます。以前はplan9のみがスキップ対象でした。
    • このコミットにより、plan9に加えてwindowsもスキップ対象に追加されました。
    • この変更の理由は、コミットメッセージにも明記されている通り、「setIPv4MulticastInterfaceが実装されていないため」です。Goのnetパッケージは、各OSのネットワークスタックと連携して動作します。マルチキャスト通信、特に特定のインターフェースを介したマルチキャストの送受信には、OSが提供する低レベルなAPI(例えば、WindowsのWinsock APIにおけるIP_MULTICAST_IFオプションの設定など)を呼び出す必要があります。当時のGoのWindows実装では、このsetIPv4MulticastInterfaceに相当する機能がまだGoのsyscallパッケージやnetパッケージに統合されていなかったため、テストが実行されると未実装のコードパスに到達し、パニックやエラーを引き起こしていました。
    • テストが失敗する原因がGoのバグではなく、OS固有の機能の未実装にある場合、そのOSでテストをスキップすることは一般的なプラクティスです。これにより、CI/CDパイプラインでのテストの失敗を防ぎ、他のプラットフォームでのテスト結果の信頼性を維持することができます。将来的には、WindowsでのsetIPv4MulticastInterfaceの実装が進めば、このテストもWindowsで有効化される可能性があります。

これらの変更は、Go言語が多様なOS環境で一貫した動作を提供するための継続的な努力の一環であり、特にWindowsのような複雑なOS環境でのネットワークプログラミングの課題に対処していることを示しています。

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

このコミットでは、以下の2つのファイルが変更されています。

  1. src/pkg/net/multicast_test.go

    --- a/src/pkg/net/multicast_test.go
    +++ b/src/pkg/net/multicast_test.go
    @@ -86,7 +86,7 @@ func TestListenMulticastUDP(t *testing.T) {
     
     func TestSimpleListenMulticastUDP(t *testing.T) {
     	switch runtime.GOOS {
    -	case "plan9":
    +	case "plan9", "windows":
     		return
     	}
     
    
  2. src/pkg/net/sockopt_windows.go

    --- a/src/pkg/net/sockopt_windows.go
    +++ b/src/pkg/net/sockopt_windows.go
    @@ -27,11 +27,7 @@ func setDefaultSockopts(s syscall.Handle, f, t int) error {
     	// to be handled by the correct socket.
     
     	// Allow broadcast.
    -\terr := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)\n-\tif err != nil {\n-\t\treturn os.NewSyscallError(\"setsockopt\", err)\n-\t}\n-\n+\tsyscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)\n     	return nil
     }\n     
    

コアとなるコードの解説

src/pkg/net/multicast_test.go の変更

  • 変更前:

    	switch runtime.GOOS {
    	case "plan9":
    		return
    	}
    

    TestSimpleListenMulticastUDP関数は、runtime.GOOS"plan9"の場合にのみテストをスキップしていました。

  • 変更後:

    	switch runtime.GOOS {
    	case "plan9", "windows":
    		return
    	}
    

    switch文のcase"windows"が追加されました。これにより、GoプログラムがWindows上で実行されている場合、TestSimpleListenMulticastUDPテストは即座にreturnし、テストの残りの部分が実行されなくなります。 この変更は、Windows環境でsetIPv4MulticastInterfaceが未実装であるためにテストが失敗する問題を回避するためのものです。テストが失敗する原因がGoのバグではなく、OS固有の機能の未実装にあるため、テストスイート全体の安定性を保つためにこのテストをスキップする判断がなされました。

src/pkg/net/sockopt_windows.go の変更

  • 変更前:

    	// Allow broadcast.
    	err := syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
    	if err != nil {
    		return os.NewSyscallError("setsockopt", err)
    	}
    

    setDefaultSockopts関数内で、SO_BROADCASTソケットオプションを設定するためにsyscall.SetsockoptIntを呼び出し、その戻り値のエラーをチェックしていました。エラーが発生した場合は、os.NewSyscallErrorを生成して呼び出し元に返していました。

  • 変更後:

    	// Allow broadcast.
    	syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1)
    

    syscall.SetsockoptIntの呼び出しはそのままですが、その戻り値のエラーをerr変数で受け取ることなく、またエラーチェックのifブロックも削除されました。これにより、SO_BROADCASTオプションの設定時にエラーが発生しても、そのエラーは無視され、関数は常にnil(エラーなし)を返すようになります(関数の最後のreturn nilによって)。 この変更は、Windows環境においてSO_BROADCASTの設定がエラーを返すことがあっても、それが常に致命的な問題ではないという判断に基づいています。エラーを無視することで、Windowsでのネットワーク機能の利用における不必要な中断を避け、より堅牢な動作を実現しています。

関連リンク

参考にした情報源リンク