[インデックス 19677] ファイルの概要
このコミットは、Go言語のネットワークパッケージにおいて、Androidプラットフォームでのgetaddrinfo
システムコールにおけるAI_ALL
フラグの使用を停止することを目的としています。これにより、Android環境でのネットワークアドレス解決の安定性と予測可能性が向上します。
コミット
- コミットハッシュ:
9416fb8c81e25c0900d06f3f04a7508671ad4c09
- 作者: David Crawshaw david.crawshaw@zentus.com
- コミット日時: 2014年7月8日 火曜日 13:42:14 -0400
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9416fb8c81e25c0900d06f3f04a7508671ad4c09
元コミット内容
net: no AI_ALL on android
LGTM=bradfitz
R=golang-codereviews, bradfitz
CC=golang-codereviews
https://golang.org/cl/112800043
変更の背景
この変更の背景には、Android環境におけるgetaddrinfo
システムコールの挙動に関する潜在的な問題があります。AI_ALL
フラグは、ホスト名に関連付けられたすべての利用可能なアドレス(IPv4とIPv6の両方、および同じアドレスファミリー内の複数のアドレス)を要求するために使用されます。しかし、Androidの特定のバージョンやデバイス構成では、AI_ALL
フラグを使用すると、以下のような問題が発生する可能性がありました。
- パフォーマンスの低下: すべてのアドレスを解決しようとすると、特にモバイル環境では、DNS解決に時間がかかったり、リソースを多く消費したりする可能性があります。
- 予期せぬ挙動: Androidのネットワークスタックが
AI_ALL
によって返される複数のアドレスを適切に処理しない場合、接続の失敗や誤ったアドレス選択につながる可能性があります。 - 互換性の問題: 特定のAndroidバージョンやカスタムROMにおいて、
AI_ALL
の挙動が標準的なLinuxディストリビューションと異なる場合があり、これが不安定性の原因となることが考えられます。
このコミットは、これらの問題を回避し、Android上でのGoアプリケーションのネットワーク動作をより予測可能で安定したものにするために、AndroidではAI_ALL
フラグを使用しないように変更しています。
前提知識の解説
getaddrinfo
getaddrinfo
は、POSIX標準で定義されているネットワークアドレスおよびサービス変換のためのAPIです。これは、ホスト名とサービス名(ポート番号など)を、ソケット接続に使用できるソケットアドレス構造体(sockaddr
)のリストに変換するために使用されます。従来のgethostbyname
やgetservbyname
といった関数よりも柔軟で、IPv4とIPv6の両方をサポートし、非同期的な解決も可能です。
AI_ALL
フラグ
getaddrinfo
関数に渡されるヒント構造体(addrinfo
)のai_flags
フィールドに設定できるフラグの一つです。AI_ALL
が設定されると、getaddrinfo
はホスト名に関連付けられたすべての利用可能なアドレスを返そうとします。これには、IPv4とIPv6のアドレス、および同じアドレスファミリー内で複数のネットワークインターフェースに関連付けられたアドレスが含まれる場合があります。
AI_CANONNAME
フラグ
これもgetaddrinfo
のai_flags
に設定できるフラグの一つです。AI_CANONNAME
が設定されると、getaddrinfo
は解決されたホストの「正規名」(canonical name)を返します。これは、エイリアスではなく、ホストの正式なDNS名です。
Cgo
Cgoは、Go言語がC言語のコードを呼び出すためのメカニズムです。Goプログラム内でCの関数やライブラリを使用することを可能にします。Goの標準ライブラリ、特にnet
パッケージは、OSのシステムコール(getaddrinfo
など)を呼び出すためにCgoを内部的に使用することがあります。
Go net
パッケージ
Go言語の標準ライブラリの一部であり、ネットワークプログラミングのための基本的な機能を提供します。TCP/IP、UDP、Unixドメインソケットなどのネットワークプロトコルをサポートし、DNS解決、接続の確立、データの送受信などの機能を提供します。
ビルドタグ (+build
)
Go言語のコンパイラディレクティブで、特定のファイルが特定のビルド条件(OS、アーキテクチャ、タグなど)の下でのみコンパイルされるように指定するために使用されます。例えば、// +build android
はAndroid向けビルドでのみコンパイルされ、// +build !android
はAndroid以外のビルドでのみコンパイルされます。
技術的詳細
Goのnet
パッケージは、ホスト名の解決にCgoを介してC標準ライブラリのgetaddrinfo
関数を利用しています。このコミット以前は、Linuxシステム(Androidを含む)では、getaddrinfo
に渡されるフラグが、AI_ALL
を含む可能性のある一般的な設定になっていたと考えられます。
このコミットでは、Androidプラットフォームに特化したcgoAddrInfoFlags()
関数を導入し、この関数がC.AI_CANONNAME
のみを返すように変更しました。これにより、Android上でのgetaddrinfo
呼び出しは、ホストの正規名のみを要求し、AI_ALL
によって引き起こされる可能性のある複雑なアドレス解決を回避します。
具体的には、src/pkg/net/cgo_android.go
という新しいファイルが作成され、このファイルには// +build cgo,!netgo
というビルドタグと、Android固有のcgoAddrInfoFlags()
の実装が含まれています。一方、既存のsrc/pkg/net/cgo_linux.go
ファイルは、ビルドタグが// +build !android,cgo,!netgo
に変更されました。この変更により、cgo_linux.go
はAndroid向けビルドではコンパイルされなくなり、Android固有のcgo_android.go
が代わりに利用されるようになります。
この分離により、GoランタイムはAndroid環境でのネットワークアドレス解決の挙動をより細かく制御できるようになり、AI_ALL
が引き起こす可能性のある問題を回避し、より安定したネットワーク動作を実現します。
コアとなるコードの変更箇所
このコミットによる主要なコード変更は以下の2つのファイルにあります。
-
src/pkg/net/cgo_android.go
:- このファイルは新規作成されました。
- Androidプラットフォームに特化した
cgoAddrInfoFlags()
関数を定義しています。 - ビルドタグ
// +build cgo,!netgo
が付与されています。
--- /dev/null +++ b/src/pkg/net/cgo_android.go @@ -0,0 +1,14 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build cgo,!netgo + +package net + +//#include <netdb.h> +import "C" + +func cgoAddrInfoFlags() C.int { + return C.AI_CANONNAME +}
-
src/pkg/net/cgo_linux.go
:- 既存のファイルのビルドタグが変更されました。
- 変更前:
// +build cgo,!netgo
- 変更後:
// +build !android,cgo,!netgo
--- a/src/pkg/net/cgo_linux.go +++ b/src/pkg/net/cgo_linux.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build cgo,!netgo +// +build !android,cgo,!netgo package net
コアとなるコードの解説
src/pkg/net/cgo_android.go
このファイルは、Goのnet
パッケージがAndroid上でCgoを使用してアドレス情報を解決する際に、getaddrinfo
関数に渡すフラグを定義しています。
func cgoAddrInfoFlags() C.int {
return C.AI_CANONNAME
}
cgoAddrInfoFlags()
関数は、C.AI_CANONNAME
という整数値を返します。これは、getaddrinfo
がホストの正規名のみを解決するように指示するフラグです。これにより、Android環境ではAI_ALL
フラグが使用されなくなり、前述の潜在的な問題が回避されます。
// +build cgo,!netgo
というビルドタグは、このファイルがCgoが有効で、かつGo独自のネットワーク実装(netgo
)が使用されていない場合にのみコンパイルされることを意味します。これは、GoがCライブラリのgetaddrinfo
を使用するシナリオに適用されます。
src/pkg/net/cgo_linux.go
このファイルは、Android以外のLinuxシステムにおけるgetaddrinfo
のフラグ設定を扱います。
// +build !android,cgo,!netgo
ビルドタグが// +build !android,cgo,!netgo
に変更されたことで、このファイルはAndroid向けにビルドされる際にはコンパイルされなくなります。これにより、Android固有のcgo_android.go
が優先され、Linux(Android以外)とAndroidで異なるgetaddrinfo
のフラグ設定が可能になります。
この変更は、Goのクロスプラットフォーム対応において、特定のOSの挙動の違いを吸収し、それぞれのプラットフォームで最適なパフォーマンスと安定性を確保するための典型的なアプローチを示しています。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/9416fb8c81e25c0900d06f3f04a7508671ad4c09
- Go Code Review (CL): https://golang.org/cl/112800043
参考にした情報源リンク
getaddrinfo
に関する一般的な情報:- Androidにおける
getaddrinfo
の挙動に関する一般的な問題(AI_ALL
に直接言及はないが、背景情報として): - Go言語のビルドタグに関する情報:
- Cgoに関する情報: