[インデックス 13633] ファイルの概要
このコミットは、Go言語の標準ライブラリであるos/exec
パッケージのテストファイルであるsrc/pkg/os/exec/exec_test.go
に影響を与えています。具体的には、NetBSD環境におけるファイルディスクリプタのテストに関する問題に対応するための変更です。
コミット
commit 2ab18f69a6eb76951f5e06bf6e291cdd56a827b4
Author: Joel Sing <jsing@google.com>
Date: Thu Aug 16 02:06:21 2012 +1000
os/exec: disable additional file descriptor test on netbsd
This currently fails on NetBSD due to the cloned file descriptors
that result from opening /dev/urandom. Disable the additional checking
until this is investigated and properly fixed.
R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/6443129
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2ab18f69a6eb76951f5e06bf6e291cdd56a827b4
元コミット内容
このコミットは、Go言語のos/exec
パッケージにおける追加のファイルディスクリプタテストをNetBSD上で無効化することを目的としています。
コミットメッセージによると、このテストは現在NetBSD上で失敗しており、その原因は/dev/urandom
を開くことによって生じる「クローンされたファイルディスクリプタ」にあるとされています。この問題が調査され、適切に修正されるまでの間、追加のチェックを無効にすることが決定されました。
変更の背景
Go言語のos/exec
パッケージは、外部コマンドを実行するための機能を提供します。このパッケージには、実行されたプロセスが予期せぬファイルディスクリプタ(FD)を開いたままにしないことを検証するためのテストが含まれています。これは、リソースリークやセキュリティ上の問題を避けるために重要です。
しかし、NetBSD環境において、このファイルディスクリプタのチェックが失敗するという問題が発生していました。具体的には、テストプロセス内で/dev/urandom
(乱数生成のためのデバイスファイル)を開くと、そのファイルディスクリプタが予期せず「クローン」され、テストが期待するFDの状態と異なる結果になっていました。
この問題は、GoのIssueトラッカーでIssue 3955として報告されており、このコミットはその一時的な回避策として、NetBSD上でのみ該当のテスト部分をスキップするように変更されました。これは、テストスイート全体の安定性を確保し、より根本的な解決策が開発されるまでの間、CI/CDパイプラインがブロックされるのを防ぐための措置です。
前提知識の解説
- ファイルディスクリプタ (File Descriptor, FD): Unix系オペレーティングシステムにおいて、プロセスがファイルやソケット、パイプなどのI/Oリソースにアクセスする際に使用する抽象的な識別子です。各プロセスは、開いているリソースに対して一意の整数値のFDを持ちます。例えば、標準入力はFD 0、標準出力はFD 1、標準エラーはFD 2です。
os/exec
パッケージ (Go言語): Go言語の標準ライブラリの一部で、外部コマンドを実行するための機能を提供します。このパッケージを使用すると、新しいプロセスを起動し、その標準入出力にアクセスしたり、終了ステータスを取得したりすることができます。/dev/urandom
: Unix系システムにおける擬似乱数生成器のデバイスファイルです。このファイルから読み取ることで、暗号学的に安全な乱数バイト列を取得できます。多くのアプリケーションで、セッションキーの生成やパスワードのハッシュ化など、セキュリティが要求される場面で利用されます。- NetBSD: オープンソースのUnix系オペレーティングシステムの一つで、高い移植性を特徴としています。様々なハードウェアアーキテクチャで動作します。このコミットの背景にある問題は、NetBSDの特定のカーネル動作やシステムコール実装に起因する可能性が示唆されています。
- クローンされたファイルディスクリプタ:
通常、
fork()
システムコールなどでプロセスが複製されると、親プロセスの開いているファイルディスクリプタは子プロセスに継承されます。しかし、ここで言及されている「クローンされたファイルディスクリプタ」は、/dev/urandom
のオープンが原因で、予期せぬ形でFDが複製される、あるいは参照カウントが正しく管理されないといった、より複雑なOSレベルの挙動を示唆している可能性があります。これは、Goのテストが期待するFDの状態(例えば、特定のFDが閉じられているべき、あるいは特定のFDのみが開いているべき)と矛盾を引き起こします。 - Goのテスト (
testing
パッケージ): Go言語には、組み込みのテストフレームワークが提供されており、go test
コマンドで実行されます。テスト関数はTest
で始まり、*testing.T
型の引数を取ります。exec_test.go
のようなテストファイルは、os/exec
パッケージの機能が正しく動作するかを検証します。
技術的詳細
このコミットが対処している問題は、Goのos/exec
パッケージのテスト、特にTestHelperProcess
関数内で発生していました。このテストは、外部プロセスが実行された後に、予期せぬファイルディスクリプタが残っていないことを検証する部分を含んでいます。これは、プロセスが終了した際に、開いたままのFDがリークしないことを保証するための重要なチェックです。
問題はNetBSD環境に特有のもので、テストプロセスが/dev/urandom
を開くと、そのFDが「クローン」されるという現象が発生していました。この「クローン」が具体的に何を意味するのかは、NetBSDのカーネル内部のFD管理メカニズムに深く関連している可能性があります。考えられるシナリオとしては、以下の点が挙げられます。
- FDの参照カウントの問題:
/dev/urandom
のような特殊なデバイスファイルは、OS内部で特別な処理が行われることがあります。FDのオープン/クローズの参照カウントがGoの期待する動作と異なり、FDが閉じられた後も内部的に参照が残ってしまう。 fork
/exec
時のFD継承の特殊性:os/exec
は内部でfork
やexec
システムコールを使用します。NetBSDのこれらのシステムコール実装が、特定の条件下(特に/dev/urandom
のような特殊なFDが関与する場合)で、FDの継承やクローズオンエグゼック(FD_CLOEXEC
)の挙動に微妙な違いがある。- GoランタイムとOSの相互作用: Goランタイムが内部的にFDを管理する方法と、NetBSDカーネルがFDを管理する方法との間に、特定のシナリオで不整合が生じる。
このコミットでは、根本的な原因を特定して修正するのではなく、一時的な回避策として、NetBSDの場合にのみこの追加のFDチェックをスキップするように変更しました。これは、テストスイートがNetBSD上で継続的に実行できるようにするための実用的なアプローチです。コミットメッセージとコードコメントには、この問題がIssue 3955として追跡されていることが明記されており、将来的に根本的な修正が行われる予定であることが示唆されています。
コアとなるコードの変更箇所
変更はsrc/pkg/os/exec/exec_test.go
ファイルに対して行われました。
--- a/src/pkg/os/exec/exec_test.go
+++ b/src/pkg/os/exec/exec_test.go
@@ -337,6 +337,11 @@ func TestHelperProcess(*testing.T) {
// TODO(bradfitz): broken? Sometimes.
// http://golang.org/issue/2603
// Skip this additional part of the test for now.
+ case "netbsd":
+ // TODO(jsing): This currently fails on NetBSD due to
+ // the cloned file descriptors that result from opening
+ // /dev/urandom.
+ // http://golang.org/issue/3955
default:
// Now verify that there are no other open fds.
var files []*os.File
具体的には、TestHelperProcess
関数内のswitch runtime.GOOS
(またはそれに類するOS判定ロジック)のブロックに、case "netbsd":
の新しいケースが追加されました。
コアとなるコードの解説
追加されたコードは、Goのテストフレームワーク内で、現在のオペレーティングシステムがNetBSDであるかどうかを判定し、もしそうであれば特定のテストロジックをスキップするためのものです。
既存のコードには、既にTODO(bradfitz): broken? Sometimes.
というコメントと共に、特定のテスト部分をスキップするロジック(おそらく他のOSや特定の条件下での不安定性のため)が存在していました。今回の変更は、その既存のパターンに倣い、NetBSDに特化した条件を追加しています。
case "netbsd":
// TODO(jsing): This currently fails on NetBSD due to
// the cloned file descriptors that result from opening
// /dev/urandom.
// http://golang.org/issue/3955
このcase "netbsd":
ブロック内には、具体的なテストロジックは記述されていません。これは、このケースにマッチした場合、その後のdefault:
ブロックで実行される「追加のファイルディスクリプタチェック」のロジックが実行されないことを意味します。つまり、NetBSD上では、/dev/urandom
に関連するファイルディスクリプタのクローン問題によって失敗する可能性のあるチェックが意図的に無効化されます。
TODO
コメントは、この変更が一時的なものであり、根本的な問題(/dev/urandom
のFDクローン問題)が将来的に調査され、修正されるべきであることを明確に示しています。また、関連するGoのIssue番号(http://golang.org/issue/3955
)が記載されており、問題の追跡と解決に向けた参照情報が提供されています。
関連リンク
- Gerrit Change-ID:
https://golang.org/cl/6443129
- GoプロジェクトのコードレビューシステムであるGerritにおけるこの変更のページ。より詳細な議論やレビューコメントが確認できる可能性があります。 - Go Issue 3955:
http://golang.org/issue/3955
- このコミットが対処しているNetBSD上でのファイルディスクリプタ問題に関するGoのIssueトラッカーのエントリ。問題の詳細、議論、およびその後の解決状況が記録されています。
参考にした情報源リンク
- コミットメッセージとdiffの内容
- Go言語の
os/exec
パッケージのドキュメント (一般的な知識として) - Unix系OSにおけるファイルディスクリプタの概念 (一般的な知識として)
/dev/urandom
の機能 (一般的な知識として)- NetBSDオペレーティングシステムに関する一般的な情報 (一般的な知識として)
- Go言語のテストフレームワークに関する情報 (一般的な知識として)