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

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

このコミットは、Go言語の標準ライブラリ net パッケージにおける UnixConn 型に、CloseRead および CloseWrite メソッドを追加するものです。これらのメソッドは、Unixドメインソケット接続の読み取り側または書き込み側を個別にシャットダウンする機能を提供します。変更自体は、Go APIの変更を記録する api/next.txt ファイルへのエントリ追加として行われています。

コミット

commit bbac652b31466463d66a4731365f8e0d7f0deb5a
Author: Russ Cox <rsc@golang.org>
Date:   Sat Jun 2 23:02:39 2012 -0400

    api: add net.UnixConn's CloseRead and CloseWrite methods
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/6278045

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

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

元コミット内容

api: add net.UnixConn's CloseRead and CloseWrite methods

このコミットは、net.UnixConn 型に CloseRead および CloseWrite メソッドを追加することを目的としています。

変更の背景

ネットワークプログラミングにおいて、ソケット接続を完全に閉じるだけでなく、読み取り側または書き込み側だけを個別にシャットダウンしたい場合があります。これは「半クローズ (half-close)」または「半二重シャットダウン (half-duplex shutdown)」と呼ばれます。

特にUnixドメインソケット(net.UnixConn)のようなローカルプロセス間通信では、一方のプロセスがデータの送信を完了したが、もう一方のプロセスからの残りのデータを受信し続けたい、あるいはその逆の場合があります。例えば、クライアントがリクエストをすべて送信し終えた後、サーバーからの応答を待つ間に、自身の送信側をシャットダウンすることで、サーバーに対して「これ以上データは送らない」というシグナルを送ることができます。これにより、サーバーはクライアントからの入力ストリームの終端を検出し、リソースを解放したり、応答の送信に集中したりすることができます。

TCPソケットには既に CloseReadCloseWrite に相当する機能(net.TCPConn のメソッド)が存在しており、Unixドメインソケットにも同様の機能が求められていました。このコミットは、net.UnixConn にこれらのメソッドを追加することで、Unixドメインソケットにおいてもより柔軟な接続管理と、特定のプロトコル実装における効率的なリソース利用を可能にすることを背景としています。

前提知識の解説

Unixドメインソケット (Unix Domain Sockets, UDS)

Unixドメインソケットは、同じホスト上のプロセス間で通信を行うためのIPC (Inter-Process Communication) 機構の一つです。ネットワークソケット(TCP/IP)がネットワークを介した通信に用いられるのに対し、Unixドメインソケットはファイルシステム上のパス名(例: /tmp/mysocket)をアドレスとして使用し、カーネル内で直接データをやり取りするため、ネットワークオーバーヘッドがなく、TCP/IPソケットよりも高速で効率的な通信が可能です。

Go言語では、net パッケージの UnixConn 型がUnixドメインソケット接続を表します。

半クローズ (Half-Close)

通常のソケットの Close メソッドは、ソケットの両方向(読み取りと書き込み)を完全に閉じ、関連するリソースを解放します。しかし、半クローズは、ソケットの読み取り側または書き込み側のいずれか一方だけをシャットダウンする操作です。

  • 読み取り側のシャットダウン (CloseRead): ソケットの受信側を閉じます。これにより、それ以降の受信操作はエラー(通常はEOF)を返します。しかし、送信側は引き続きデータを送信できます。
  • 書き込み側のシャットダウン (CloseWrite): ソケットの送信側を閉じます。これにより、それ以降の送信操作はエラーを返します。送信バッファに残っているデータは送信されますが、新たなデータは送信されません。受信側は引き続きデータを受信できます。

この機能は、例えばHTTP/1.0のKeep-Alive接続や、特定のRPCプロトコルなど、クライアントがリクエストを送信し終えた後に、サーバーからの応答を待つ間、自身の送信側を閉じることで、サーバーに「これ以上データは来ない」と通知するようなシナリオで非常に有用です。

技術的詳細

CloseRead および CloseWrite メソッドは、内部的にはUnixシステムコールである shutdown(2) を利用して実装されます。

shutdown(int sockfd, int how) システムコールは、ソケット sockfd の接続の一部または全体をシャットダウンするために使用されます。how 引数によってシャットダウンのモードが指定されます。

  • SHUT_RD (または SHUT_RDWR): ソケットの読み取り側をシャットダウンします。CloseRead に対応します。
  • SHUT_WR: ソケットの書き込み側をシャットダウンします。CloseWrite に対応します。
  • SHUT_RDWR: ソケットの読み取り側と書き込み側の両方をシャットダウンします。これは Close メソッドが内部的に行う操作の一部です。

net.UnixConnCloseRead メソッドが呼び出されると、Goランタイムは対応するファイルディスクリプタに対して shutdown(fd, SHUT_RD) を実行します。同様に、CloseWriteshutdown(fd, SHUT_WR) を実行します。

これにより、OSレベルでソケットの特定の方向のデータフローが停止され、Goの net パッケージはその状態を反映して、該当する操作(読み取りまたは書き込み)に対して適切なエラー(通常はEOFまたはパイプが壊れたエラー)を返します。

このコミット自体は、api/next.txt にこれらのメソッドの存在を宣言するものであり、実際の shutdown(2) システムコールの呼び出しを含む実装コードは、Goの net パッケージの内部で既に行われているか、このAPI変更と同時に別のコミットで追加されることになります。api/next.txt は、Goの互換性保証の一部として、将来のGoバージョンで削除されないAPIを記録するための重要なファイルです。

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

このコミットによる直接的なコード変更は、api/next.txt ファイルへの以下の2行の追加です。

--- a/api/next.txt
+++ b/api/next.txt
@@ -10,6 +10,8 @@ pkg debug/elf, type FileHeader struct, Entry uint64
 pkg go/doc, var IllegalPrefixes []string
 pkg math/big, method (*Int) MarshalJSON() ([]byte, error)
 pkg math/big, method (*Int) UnmarshalJSON([]byte) error
+pkg net, method (*UnixConn) CloseRead() error
+pkg net, method (*UnixConn) CloseWrite() error
 pkg regexp/syntax, const ErrUnexpectedParen ErrorCode
 pkg syscall (darwin-386), const B0 ideal-int
 pkg syscall (darwin-386), const B110 ideal-int

コアとなるコードの解説

api/next.txt は、Go言語の次期リリースで追加される予定の新しいAPI要素を記録するためのファイルです。Goは「Go 1 Compatibility Promise」という厳格な互換性保証を持っており、一度安定版APIとして公開されたものは、特別な理由がない限り変更または削除されません。

このファイルに pkg net, method (*UnixConn) CloseRead() errorpkg net, method (*UnixConn) CloseWrite() error の2行が追加されたことは、以下のことを意味します。

  1. APIの追加: net.UnixConn 型に CloseRead()CloseWrite() という2つの新しいメソッドが追加されることが公式に決定されました。
  2. 互換性保証: これらのメソッドは、将来のGoバージョンにおいても安定したAPIとして提供され続けることが保証されます。開発者は安心してこれらのメソッドを利用できるようになります。
  3. 機能の拡張: net.UnixConn が、TCP接続と同様に、読み取り側と書き込み側を個別にシャットダウンする半クローズ機能を持つことになります。これにより、Unixドメインソケットを利用するアプリケーションの柔軟性と制御性が向上します。

このファイルへの追加は、実際のメソッド実装が完了し、テストされ、レビュープロセスを通過した後に、APIの最終的な承認を示すステップとして行われます。

関連リンク

参考にした情報源リンク

  • Go言語公式ドキュメント
  • Unix/Linux man pages (shutdown(2))
  • 一般的なネットワークプログラミングの概念(半クローズなど)