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

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

このコミットは、Go言語のnetパッケージにおけるPlan 9オペレーティングシステム向けのネットワークソケット実装に関する修正です。具体的には、以下のファイルが変更されています。

  • src/pkg/net/iprawsock_plan9.go: IP生ソケットのPlan 9実装
  • src/pkg/net/ipsock_plan9.go: IPソケットのPlan 9実装
  • src/pkg/net/tcpsock_plan9.go: TCPソケットのPlan 9実装
  • src/pkg/net/udpsock_plan9.go: UDPソケットのPlan 9実装
  • src/pkg/net/unixsock_plan9.go: UnixドメインソケットのPlan 9実装
  • src/pkg/net/unixsock_posix.go: UnixドメインソケットのPOSIX実装(関連する変更)

これらのファイルは、Goの標準ライブラリnetパッケージの一部であり、Plan 9環境下でのネットワーク通信機能を提供します。

コミット

commit b58b5ba997ad5ab5b6419a575cb5829a45097fa6
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Thu Jan 19 12:25:37 2012 +0900

    net: fix plan9 build
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/5554058

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

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

元コミット内容

net: fix plan9 build

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/5554058

変更の背景

このコミットの主な背景は、Go言語のnetパッケージにおけるタイムアウト処理のAPI変更と、それに対応するPlan 9ビルドの修正です。Goのnetパッケージでは、以前はSetTimeout, SetReadTimeout, SetWriteTimeoutといったメソッドが提供されていましたが、これらは後にSetDeadline, SetReadDeadline, SetWriteDeadlineというより汎用的なAPIに置き換えられました。

SetTimeout系のメソッドは、相対的な時間(例: 「今から5秒後」)でタイムアウトを設定するものでしたが、SetDeadline系のメソッドは、絶対的な時刻(例: 「2025年7月10日12時00分00秒」)でタイムアウトを設定します。この変更は、タイムアウト処理をより柔軟かつ正確に制御できるようにするためのものでした。

Plan 9は、Go言語が初期からサポートしているオペレーティングシステムの一つであり、そのネットワークスタックは他のOSとは異なる特性を持っています。そのため、netパッケージのAPI変更があった際には、Plan 9固有の実装もそれに合わせて更新する必要がありました。このコミットは、SetTimeoutからSetDeadlineへのAPI変更に伴い、Plan 9向けのネットワークソケット実装が正しくビルドされ、機能するように修正することを目的としています。

前提知識の解説

Go言語のnetパッケージ

Go言語のnetパッケージは、ネットワークI/Oプリミティブを提供します。TCP/IP、UDP、Unixドメインソケットなど、様々なネットワークプロトコルを扱うためのインターフェースや実装が含まれています。

net.Connインターフェース

net.Connは、ネットワーク接続を表すGoのインターフェースです。以下の主要なメソッドを定義しています。

  • Read(b []byte) (n int, err error): データを読み込みます。
  • Write(b []byte) (n int, err error): データを書き込みます。
  • Close() error: 接続を閉じます。
  • LocalAddr() Addr: ローカルネットワークアドレスを返します。
  • RemoteAddr() Addr: リモートネットワークアドレスを返します。
  • SetDeadline(t time.Time) error: 読み書き両方の操作のデッドラインを設定します。
  • SetReadDeadline(t time.Time) error: 読み込み操作のデッドラインを設定します。
  • SetWriteDeadline(t time.Time) error: 書き込み操作のデッドラインを設定します。

SetTimeout vs SetDeadline

  • SetTimeout(nsec int64) error (旧API):

    • 引数nsecはナノ秒単位の相対時間で、その時間内に操作が完了しない場合にタイムアウトエラーを発生させます。
    • このAPIは、Go 1.0のリリース後に非推奨となり、最終的に削除されました。
  • SetDeadline(t time.Time) error (新API):

    • 引数ttime.Time型で、操作が完了しなければならない絶対時刻を指定します。
    • time.Time{}(ゼロ値)を渡すと、デッドラインが無効になり、タイムアウトしなくなります。
    • SetReadDeadlineSetWriteDeadlineは、それぞれ読み込みと書き込みに特化したデッドラインを設定します。

SetDeadlineが導入された背景には、相対時間でのタイムアウト設定が、複数の操作にまたがる場合に累積的なタイムアウト計算を複雑にするという問題がありました。絶対時刻でデッドラインを設定することで、より直感的で正確なタイムアウト管理が可能になります。

os.EPLAN9

os.EPLAN9は、Plan 9オペレーティングシステム固有のエラーを表すGoのエラー定数です。Plan 9では、一部のPOSIX互換の機能がサポートされていないか、異なるセマンティクスを持つ場合があります。このコミットでは、SetDeadline系のメソッドがPlan 9環境では実際には機能しない(または実装されていない)ため、os.EPLAN9を返すことで、その制約を明示しています。これは、Plan 9のネットワークスタックがタイムアウトの概念を直接サポートしていないためと考えられます。

Plan 9

Plan 9 from Bell Labsは、ベル研究所で開発された分散オペレーティングシステムです。Unixの後継として設計され、"Everything is a file"という哲学に基づいています。ネットワークリソースを含むすべてのリソースがファイルシステムとして表現され、アクセスされます。Go言語は、Plan 9の思想に影響を受けており、初期からPlan 9への移植性が重視されていました。

技術的詳細

このコミットの技術的詳細は、GoのnetパッケージにおけるタイムアウトAPIの変更(SetTimeoutからSetDeadlineへの移行)を、Plan 9固有のネットワークソケット実装に適用することに集約されます。

Goのnet.Connインターフェースは、ネットワーク接続の抽象化を提供し、その一部としてタイムアウト設定のためのメソッドを含んでいます。Goの進化の過程で、タイムアウトの概念が相対時間から絶対時刻へと変更されました。これは、より堅牢で予測可能なタイムアウト動作を実現するためです。

具体的には、以下の変更が行われています。

  1. SetTimeout系のメソッドの削除: IPConn, plan9Conn, TCPConn, UDPConn, UnixConnといったPlan 9向けのコネクション型から、SetTimeout, SetReadTimeout, SetWriteTimeoutメソッドが削除されました。これらのメソッドは、Goの標準ライブラリ全体で非推奨となり、最終的に削除される方向性であったため、Plan 9の実装もそれに追従しました。

  2. SetDeadline系のメソッドの追加: 削除されたSetTimeout系のメソッドの代わりに、SetDeadline, SetReadDeadline, SetWriteDeadlineメソッドが追加されました。これらのメソッドは、net.Connインターフェースの新しい要件を満たすために導入されました。

  3. Plan 9固有のタイムアウト実装: Plan 9のネットワークスタックは、一般的なOS(Linux, Windows, macOSなど)とは異なり、ソケットレベルでの読み書きタイムアウトを直接サポートしていない場合があります。そのため、追加されたSetDeadline系のメソッドは、すべてos.EPLAN9エラーを返します。これは、Plan 9環境ではこれらのタイムアウト機能が利用できないことを明示するものです。これにより、GoのコードがPlan 9でビルドされた際に、タイムアウト設定が意図通りに機能しないことを開発者に伝えます。

  4. timeパッケージのインポート: SetDeadline系のメソッドはtime.Time型を引数に取るため、関連するファイル(iprawsock_plan9.go, ipsock_plan9.go, tcpsock_plan9.go, udpsock_plan9.go, unixsock_plan9.go)に"time"パッケージのインポートが追加されました。

  5. ドキュメントの更新: IPConnWriteToIPメソッドのコメントが、古いSetTimeoutSetWriteTimeoutへの参照から、新しいSetDeadlineSetWriteDeadlineへの参照に更新されました。これにより、APIの変更がドキュメントにも反映されています。

この変更は、GoのnetパッケージのAPI統一性を保ちつつ、Plan 9という特定の環境における制約を適切にハンドリングするための重要なステップです。

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

このコミットでは、主に以下のファイルでSetTimeout系のメソッドが削除され、SetDeadline系のメソッドが追加されています。

  • src/pkg/net/iprawsock_plan9.go:

    • SetTimeout, SetReadTimeout, SetWriteTimeoutメソッドが削除されました。
    • SetDeadline, SetReadDeadline, SetWriteDeadlineメソッドが追加され、すべてos.EPLAN9を返します。
    • "time"パッケージがインポートされました。
    • WriteToIPのコメントが更新されました。
  • src/pkg/net/ipsock_plan9.go:

    • plan9Conn型からSetTimeout, SetReadTimeout, SetWriteTimeoutメソッドが削除されました。
    • plan9Conn型にSetDeadline, SetReadDeadline, SetWriteDeadlineメソッドが追加され、すべてos.EPLAN9を返します。
    • "time"パッケージがインポートされました。
  • src/pkg/net/tcpsock_plan9.go:

    • TCPConn型にSetDeadline, SetReadDeadline, SetWriteDeadlineメソッドが追加され、すべてos.EPLAN9を返します。
    • "time"パッケージがインポートされました。
  • src/pkg/net/udpsock_plan9.go:

    • UDPConn型にSetDeadline, SetReadDeadline, SetWriteDeadlineメソッドが追加され、すべてos.EPLAN9を返します。
    • "time"パッケージがインポートされました。
    • ReadFromUDPWriteToUDPのコメントが更新されました。
  • src/pkg/net/unixsock_plan9.go:

    • UnixConn型からSetTimeout, SetReadTimeout, SetWriteTimeoutメソッドが削除されました。
    • UnixConn型にSetDeadline, SetReadDeadline, SetWriteDeadlineメソッドが追加され、すべてos.EPLAN9を返します。
    • "time"パッケージがインポートされました。
  • src/pkg/net/unixsock_posix.go:

    • UnixListenerSetDeadlineメソッドのコメントが、SetTimeoutからSetDeadlineへの変更を反映するように更新されました。

コアとなるコードの解説

ここでは、src/pkg/net/iprawsock_plan9.goの変更を例に、コアとなるコードの解説を行います。他のファイルでも同様のパターンで変更が適用されています。

変更前 (src/pkg/net/iprawsock_plan9.goの一部):

// SetTimeout implements the net.Conn SetTimeout method.
func (c *IPConn) SetTimeout(nsec int64) error {
	return os.EPLAN9
}

// SetReadTimeout implements the net.Conn SetReadTimeout method.
func (c *IPConn) SetReadTimeout(nsec int64) error {
	return os.EPLAN9
}

// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
func (c *IPConn) SetWriteTimeout(nsec int64) error {
	return os.EPLAN9
}

変更後 (src/pkg/net/iprawsock_plan9.goの一部):

import (
	"os"
	"time" // 新しく追加されたインポート
)

// SetDeadline implements the net.Conn SetDeadline method.
func (c *IPConn) SetDeadline(t time.Time) error {
	return os.EPLAN9
}

// SetReadDeadline implements the net.Conn SetReadDeadline method.
func (c *IPConn) SetReadDeadline(t time.Time) error {
	return os.EPLAN9
}

// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
func (c *IPConn) SetWriteDeadline(t time.Time) error {
	return os.EPLAN9
}

解説:

  1. import "time"の追加: SetDeadline系のメソッドはtime.Time型の引数を取るため、timeパッケージが新しくインポートされています。これにより、time.Time型がコード内で利用可能になります。

  2. SetTimeout系のメソッドの削除: 変更前のコードにあったSetTimeout, SetReadTimeout, SetWriteTimeoutの3つのメソッドが完全に削除されています。これは、Goのnetパッケージ全体でこれらの相対時間ベースのタイムアウトAPIが非推奨となり、SetDeadline系のAPIに置き換えられたためです。

  3. SetDeadline系のメソッドの追加: 削除されたメソッドの代わりに、SetDeadline, SetReadDeadline, SetWriteDeadlineの3つのメソッドがIPConn型に追加されています。これらのメソッドはnet.Connインターフェースの新しい定義に準拠しています。

  4. return os.EPLAN9: 追加されたすべてのSetDeadline系のメソッドは、return os.EPLAN9という行を含んでいます。これは、Plan 9オペレーティングシステムでは、これらのタイムアウト機能がネイティブにサポートされていないか、Goのnetパッケージが提供する抽象化レベルでは実装が困難であることを示しています。したがって、これらのメソッドが呼び出された場合、常にos.EPLAN9エラーが返され、タイムアウト設定が適用されないことを呼び出し元に伝えます。これは、Plan 9環境におけるGoのネットワーク機能の限界を明確にするための重要な実装です。

この変更により、GoのnetパッケージのAPIが統一され、Plan 9環境でも最新のAPI定義に準拠するようになりました。同時に、Plan 9の特性上、タイムアウト機能が利用できないという事実も透過的に扱われています。

関連リンク

参考にした情報源リンク