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

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

このコミットは、Go言語の標準ライブラリ net パッケージにおける、Darwin (macOS) 環境での SO_LINGER_SEC ソケットオプションの使用に関する変更を元に戻すものです。具体的には、以前のコミットで導入された SO_LINGER_SEC の利用を廃止し、代わりに一般的な SO_LINGER オプションを使用するように戻しています。これは、特定のプラットフォーム固有のソケットオプションが意図しない問題を引き起こした可能性、またはその必要性がなくなったことを示唆しています。

コミット

commit c91aea6c31374852c2d50a2a94b286c6c5d55ae0
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date:   Mon May 12 08:48:19 2014 -0700

    undo CL 92210044 / 5cb21eee2d35
    
    <enter reason for undo>
    
    ««« original CL description
    net: make use of SO_LINGER_SEC on darwin
    
    Fixes #7971.
    
    LGTM=iant
    R=golang-codereviews, iant
    CC=golang-codereviews
    https://golang.org/cl/92210044
    »»»
    
    TBR=iant
    R=golang-codereviews
    CC=golang-codereviews
    https://golang.org/cl/96220049
---
 src/pkg/net/sockopt_posix.go | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/src/pkg/net/sockopt_posix.go b/src/pkg/net/sockopt_posix.go
index 0bfaecea41..921918c37f 100644
--- a/src/pkg/net/sockopt_posix.go
+++ b/src/pkg/net/sockopt_posix.go
@@ -8,7 +8,6 @@ package net
 
  import (
  	"os"
-	"runtime"
  	"syscall"
  )
  
@@ -138,9 +137,5 @@ func setLinger(fd *netFD, sec int) error {
  		return err
  	}
  	defer fd.decref()
-\topt := syscall.SO_LINGER
-\tif runtime.GOOS == "darwin" {\n-\t\topt = syscall.SO_LINGER_SEC\n-\t}\n-\treturn os.NewSyscallError("setsockopt", syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, opt, &l))\n+\treturn os.NewSyscallError("setsockopt", syscall.SOL_SOCKET, syscall.SO_LINGER, &l))\n }\n

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

https://github.com/golang/go/commit/c91aea6c31374852c2d50a2a94b286c6c5d55ae0

元コミット内容

net: make use of SO_LINGER_SEC on darwin

Fixes #7971.

変更の背景

このコミットは、以前のコミット (CL 92210044) で導入された変更を元に戻すものです。元のコミットは、Goの net パッケージがDarwin (macOS) 環境でソケットオプション SO_LINGER_SEC を使用するように変更しました。しかし、この「undo」コミットは、その変更が何らかの理由で問題を引き起こしたか、あるいは不要になったために元に戻されたことを示しています。コミットメッセージには具体的な「undoの理由」が記載されていませんが、一般的にこのような変更の巻き戻しは、導入された機能が期待通りに動作しなかった、互換性の問題が発生した、またはより良い解決策が見つかった場合に発生します。

SO_LINGER_SEC はDarwin固有のソケットオプションであり、SO_LINGER とは異なる動作をする可能性があります。元のコミットは、特定のバグ (#7971) を修正するために SO_LINGER_SEC を導入したようですが、その修正が他の問題を引き起こしたか、あるいは SO_LINGER_SEC の使用がGoのクロスプラットフォームな設計思想に合致しなかった可能性が考えられます。

前提知識の解説

ソケットオプション (Socket Options)

ソケットオプションは、ネットワークソケットの動作を制御するための設定です。setsockopt システムコールを使用して設定され、getsockopt システムコールで取得されます。これらのオプションは、ソケットのバッファサイズ、タイムアウト、再利用、接続の挙動など、多岐にわたる側面を調整するために使用されます。

SO_LINGER

SO_LINGER は、ソケットが閉じられたときの挙動を制御するソケットオプションです。通常、ソケットを閉じると、システムはバックグラウンドで残りのデータを送信しようとします。しかし、SO_LINGER を設定すると、この挙動を変更できます。

SO_LINGERstruct linger という構造体を使って設定されます。この構造体には通常、以下の2つのフィールドがあります。

  • l_onoff: 0以外の場合、lingerオプションが有効になります。0の場合、無効になります。
  • l_linger: l_onoff が0以外の場合に有効なタイムアウト値(秒単位)を指定します。

SO_LINGER が有効で l_linger が0より大きい場合、close() システムコールは、ソケットの送信バッファに残っているデータがすべて送信されるか、または指定されたタイムアウト時間が経過するまでブロックします。タイムアウト時間内にデータが送信されなかった場合、残りのデータは破棄されます。

SO_LINGER が有効で l_linger が0の場合、close() システムコールは即座に返り、ソケットの送信バッファに残っているデータはすべて破棄され、TCP RST (Reset) パケットがピアに送信されます。これは、通常のTCPの優雅なシャットダウンシーケンス(FIN/ACK)をバイパスし、接続を強制的に終了させます。これは TIME_WAIT 状態を回避するために使用されることがありますが、データ損失のリスクがあります。

SO_LINGER_SEC (Darwin固有)

SO_LINGER_SEC は、Darwin (macOS) オペレーティングシステムに特有のソケットオプションです。その機能は SO_LINGER と似ていますが、SO_LINGER_SEC は直接タイムアウト値を秒単位で設定するために使用されるようです。これは、SO_LINGERstruct linger を介して l_onoffl_linger の両方を設定するのに対し、SO_LINGER_SEC はタイムアウト値のみを直接設定する、より簡略化されたインターフェースである可能性があります。

setsockopt システムコール

setsockopt は、ソケットのオプションを設定するために使用されるシステムコールです。そのシグネチャは通常以下のようになります。 int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

  • sockfd: オプションを設定するソケットのファイルディスクリプタ。
  • level: オプションが定義されているプロトコルレベル(例: SOL_SOCKET はソケットレベルのオプション)。
  • optname: 設定するオプションの名前(例: SO_LINGER, SO_LINGER_SEC)。
  • optval: オプションの値へのポインタ。
  • optlen: optval のサイズ。

Go言語の syscall パッケージ

Go言語の syscall パッケージは、低レベルのオペレーティングシステムプリミティブへのアクセスを提供します。これには、システムコール(例: setsockopt)や、OS固有の定数(例: syscall.SO_LINGER, syscall.SO_LINGER_SEC, syscall.SOL_SOCKET)が含まれます。このパッケージは、Goの標準ライブラリがOS固有の機能とやり取りするために内部的に使用されます。

Go言語の net パッケージ

Go言語の net パッケージは、ネットワークI/Oのポータブルなインターフェースを提供します。TCP/IP、UDP、Unixドメインソケットなどのネットワークプロトコルをサポートし、高レベルの抽象化を提供します。しかし、内部的には syscall パッケージを使用して、OS固有のソケット操作を実行することがあります。

CL (Change List)

Goプロジェクトにおける「CL」は「Change List」の略で、コードレビューシステムGerritで管理される一連の変更を指します。これは、他のプロジェクトにおけるプルリクエストやマージリクエストに相当します。各CLには一意の番号が割り当てられ、コードの変更、コミットメッセージ、レビューの履歴が含まれます。

技術的詳細

このコミットの技術的詳細は、Goの net パッケージがソケットの linger 挙動をどのように扱うか、特にクロスプラットフォームの互換性とDarwin固有の挙動に焦点を当てています。

元のコミット (CL 92210044) は、Darwin環境でのみ syscall.SO_LINGER_SEC を使用するように setLinger 関数を変更しました。これは、おそらくDarwin上での SO_LINGER の挙動に問題があったか、または SO_LINGER_SEC を使用することで特定のパフォーマンスや信頼性の向上が期待されたためと考えられます。

しかし、この「undo」コミットは、その変更が元に戻されたことを意味します。考えられる理由はいくつかあります。

  1. 互換性の問題: SO_LINGER_SEC の使用が、Goの net パッケージの他の部分や、Goアプリケーションが依存する他のライブラリとの間で予期せぬ互換性の問題を引き起こした可能性があります。
  2. バグの再発または新たなバグの導入: SO_LINGER_SEC の導入が、元のバグ (#7971) を完全に修正しなかったか、あるいは新たなバグやエッジケースを導入した可能性があります。
  3. 複雑性の増加: プラットフォーム固有のソケットオプションを使用することは、コードベースの複雑性を増加させ、メンテナンスを困難にする可能性があります。もし SO_LINGER が最終的にDarwin上でも期待通りに動作することが判明した場合、SO_LINGER_SEC のような特殊なオプションを使用する必要はなくなります。
  4. Goのクロスプラットフォーム原則: Goはクロスプラットフォームな開発を強く志向しています。可能な限り、OS固有のコードを最小限に抑え、共通のインターフェースを通じて機能を提供することが望ましいです。SO_LINGER_SEC のようなDarwin固有のオプションの使用は、この原則から逸脱するものであり、最終的に標準の SO_LINGER に戻すことが決定された可能性があります。
  5. SO_LINGER_SEC の挙動の誤解: SO_LINGER_SEC の挙動が当初の理解と異なっていた、または特定のシナリオで問題を引き起こすことが判明した可能性もあります。

このコミットは、src/pkg/net/sockopt_posix.go ファイルから runtime パッケージのインポートを削除し、runtime.GOOS == "darwin" のチェックをなくすことで、Darwin固有のロジックを排除しています。これにより、setLinger 関数はすべてのPOSIX互換システムで一貫して syscall.SO_LINGER を使用するようになります。

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

--- a/src/pkg/net/sockopt_posix.go
+++ b/src/pkg/net/sockopt_posix.go
@@ -8,7 +8,6 @@ package net
 
  import (
  	"os"
-	"runtime"
  	"syscall"
  )
  
@@ -138,9 +137,5 @@ func setLinger(fd *netFD, sec int) error {
  		return err
  	}
  	defer fd.decref()
-\topt := syscall.SO_LINGER
-\tif runtime.GOOS == "darwin" {\n-\t\topt = syscall.SO_LINGER_SEC\n-\t}\n-\treturn os.NewSyscallError("setsockopt", syscall.SOL_SOCKET, opt, &l))\n+\treturn os.NewSyscallError("setsockopt", syscall.SOL_SOCKET, syscall.SO_LINGER, &l))\n }\n

コアとなるコードの解説

このコミットは、src/pkg/net/sockopt_posix.go ファイル内の setLinger 関数に焦点を当てた変更です。

  1. runtime パッケージのインポート削除:

    -	"runtime"
    

    以前のコミットでは、runtime.GOOS を使用して現在のOSがDarwinであるかどうかを判定していました。このコミットでは、Darwin固有のロジックが削除されるため、runtime パッケージは不要となり、インポートリストから削除されました。これは、コードの依存関係を減らし、クリーンアップする良いプラクティスです。

  2. setLinger 関数のロジック変更:

    -	opt := syscall.SO_LINGER
    -	if runtime.GOOS == "darwin" {
    -		opt = syscall.SO_LINGER_SEC
    -	}
    -	return os.NewSyscallError("setsockopt", syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, opt, &l))\n
    +	return os.NewSyscallError("setsockopt", syscall.SetsockoptLinger(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_LINGER, &l))\n
    

    これがこのコミットの最も重要な変更点です。

    • 元のコードでは、まず opt 変数を syscall.SO_LINGER で初期化し、もし実行環境がDarwinであれば syscall.SO_LINGER_SEC に上書きしていました。これは、Darwinでのみ SO_LINGER_SEC を使用するという条件付きロジックでした。
    • 変更後のコードでは、この条件付きロジックが完全に削除されました。代わりに、setsockopt システムコールを呼び出す際に、常に syscall.SO_LINGER を使用するようにハードコードされています。

この変更により、setLinger 関数は、どのPOSIX互換システムで実行されても、ソケットのlingerオプションを設定する際に SO_LINGER を使用するようになります。これにより、Goの net パッケージのソケットlinger挙動が、Darwinを含むすべてのサポート対象プラットフォームで一貫したものになります。

関連リンク

  • 元の変更リスト (CL 92210044): https://golang.org/cl/92210044 (ただし、このリンクは現在、コミットメッセージに記載されている内容とは異なるCLを示している可能性があります。GoのCL番号は再利用されることがあるため、注意が必要です。)
  • この変更リスト (CL 96220049): https://golang.org/cl/96220049
  • 関連するGoのIssue #7971: https://github.com/golang/go/issues/7971 (このIssueは、元のCLが修正しようとした問題に関連しています。)

参考にした情報源リンク