[インデックス 11720] ファイルの概要
このコミットは、Go言語のコマンドラインツールであるgo tool
の呼び出しにおいて、標準入力(stdin)を使用できるようにする変更を導入しています。これにより、go tool
が対話的な操作やパイプからの入力をより適切に処理できるようになり、特定のツール(例: go tool pprof
)の使い勝手が向上しました。
コミット
commit 56ade2d8d5ca27a91ab829499cc0b0576f3297aa
Author: Russ Cox <rsc@golang.org>
Date: Wed Feb 8 16:14:24 2012 -0500
cmd/go: let go tool invocation use stdin
Fixes #2921.
R=golang-dev, n13m3y3r
CC=golang-dev
https://golang.org/cl/5647057
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/56ade2d8d5ca27a91ab829499cc0b0576f3297aa
元コミット内容
cmd/go: let go tool invocation use stdin
Fixes #2921.
R=golang-dev, n13m3y3r
CC=golang-dev
https://golang.org/cl/5647057
変更の背景
この変更は、Go言語のIssue #2921「'go tool pprof' does not start pprof in interactive mode」を修正するために行われました。go tool pprof
のようなツールは、プロファイリングデータを分析する際に、ユーザーからの対話的な入力や、パイプを通じて渡されるデータを受け取る必要があります。しかし、当時のgo tool
の内部実装では、実行されるサブプロセスに標準入力が適切に渡されていませんでした。このため、go tool pprof
が対話モードで起動せず、ユーザーがプロファイリングデータを効率的に操作できないという問題が発生していました。
このコミットは、go tool
が内部で他のコマンドを実行する際に、親プロセスの標準入力を子プロセスに引き継ぐようにすることで、この問題を解決しています。これにより、go tool
を介して実行されるツールが、期待通りに標準入力からのデータを受け取れるようになり、対話的な利用やパイプライン処理が可能になりました。
前提知識の解説
go tool
コマンド
go tool
は、Go言語のツールチェインに含まれる低レベルなコマンドを実行するためのユーティリティです。go build
やgo run
のような高レベルなコマンドとは異なり、go tool
はコンパイラ(compile
)、アセンブラ(asm
)、リンカ(link
)、プロファイラ(pprof
)など、Goのビルドシステムや開発環境を構成する個々のツールを直接呼び出すために使用されます。通常、開発者が直接go tool
を使う機会は少ないですが、特定のデバッグや高度なビルド操作を行う際に利用されます。
標準入出力(stdin, stdout, stderr)
UNIXライクなシステムでは、すべてのプロセスはデフォルトで3つの標準ストリームを持っています。
- 標準入力 (stdin): プロセスがデータを読み込むための入力ストリームです。通常、キーボードからの入力や、パイプ(
|
)で前のコマンドの出力が渡される場所です。 - 標準出力 (stdout): プロセスが通常の出力データを書き込むための出力ストリームです。通常、ターミナルに表示されるか、リダイレクト(
>
)でファイルに書き込まれます。 - 標準エラー出力 (stderr): プロセスがエラーメッセージや診断情報を書き込むための出力ストリームです。通常、標準出力とは別にターミナルに表示されるか、別のファイルにリダイレクトされます。
コマンドラインツールが対話的に動作したり、パイプラインの一部として機能したりするためには、これらの標準ストリームを適切に扱うことが不可欠です。
os/exec
パッケージ
Go言語の標準ライブラリであるos/exec
パッケージは、外部コマンドを実行するための機能を提供します。このパッケージを使用することで、Goプログラムからシェルコマンドや他の実行可能ファイルを起動し、その入出力を制御することができます。
os/exec
パッケージの主要な構造体はexec.Cmd
です。この構造体は、実行するコマンドのパス、引数、環境変数、そして標準入出力ストリーム(Stdin
, Stdout
, Stderr
フィールド)などを設定するために使用されます。
技術的詳細
このコミットの技術的な核心は、os/exec
パッケージのexec.Cmd
構造体のStdin
フィールドの利用にあります。
exec.Cmd
構造体には、実行される子プロセスの標準入力を設定するためのStdin
フィールドがあります。このフィールドはio.Reader
インターフェースを満たす任意のオブジェクトを受け取ることができます。
Stdin: nil
(デフォルト): 子プロセスは標準入力を持たず、入力しようとするとEOF(End Of File)を受け取ります。Stdin: os.Stdin
: 子プロセスの標準入力が、親プロセスの標準入力(つまり、go
コマンド自体が受け取っている標準入力)に接続されます。これにより、親プロセスに渡された入力がそのまま子プロセスに流れるようになります。
この変更以前は、go tool
が内部で呼び出すコマンドのStdin
フィールドは明示的に設定されていなかったため、デフォルトのnil
状態でした。そのため、子プロセスは標準入力からの入力を受け取ることができず、対話的な動作が不可能でした。
このコミットでは、toolCmd.Stdin = os.Stdin
という一行を追加することで、この問題を解決しています。これにより、go tool
が実行するサブコマンドは、go
コマンドが受け取った標準入力をそのまま利用できるようになり、対話的な操作やパイプからのデータ処理が可能になりました。
コアとなるコードの変更箇所
--- a/src/cmd/go/tool.go
+++ b/src/cmd/go/tool.go
@@ -70,6 +70,7 @@ func runTool(cmd *Command, args []string) {
toolCmd := &exec.Cmd{
Path: toolPath,
Args: args,
+ Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
}
コアとなるコードの解説
変更はsrc/cmd/go/tool.go
ファイルのrunTool
関数内で行われています。この関数は、go tool
コマンドが内部で他のツールを実行する際に呼び出されます。
変更前のコードでは、exec.Cmd
構造体の初期化時にStdin
フィールドが明示的に設定されていませんでした。Goでは、構造体のフィールドが初期化時に明示的に値が与えられない場合、その型のゼロ値で初期化されます。io.Reader
インターフェースのゼロ値はnil
であるため、Stdin
はnil
となっていました。
追加された一行 Stdin: os.Stdin,
は、toolCmd
というexec.Cmd
構造体のStdin
フィールドに、os.Stdin
という値を代入しています。
os.Stdin
は、Goプログラムが起動された際に自動的に開かれる標準入力ファイルディスクリプタを表す*os.File
型(io.Reader
インターフェースを満たす)のグローバル変数です。
この変更により、go tool
によって起動される子プロセス(例: pprof
)は、親プロセスであるgo
コマンドの標準入力を共有するようになります。結果として、ユーザーがgo tool pprof
を実行し、キーボードから入力したり、他のコマンドの出力をパイプで渡したりした場合、その入力がpprof
ツールに正しく渡されるようになります。これにより、pprof
のような対話的なツールが期待通りに動作するようになり、Issue #2921が解決されました。
関連リンク
- Go Issue #2921: 'go tool pprof' does not start pprof in interactive mode
- Go CL 5647057: cmd/go: let go tool invocation use stdin
参考にした情報源リンク
- GitHub Issue #2921 in the
golang/go
repository: This issue, titled "'go tool pprof' does not start pprof in interactive mode," was opened in 2012 and has since been fixed and marked as "FrozenDueToAge." - Go Packages Vulnerability Report GO-2024-2921: This is a recent vulnerability report (published July 1, 2024) concerning
github.com/hashicorp/vault
. It describes how HashiCorp Vault incorrectly validated JSON Web Tokens (JWT) Audience Claims, identified as CVE-2024-5798 and GHSA-32cj-5wx4-gq8p. - EulerOS-SA-2024-2921 (Vulnerability Database Entry): This refers to a vulnerability in
golang
on EulerOS 2.0 SP12 (CVE-2024-24791). It describes how thenet/http
HTTP/1.1 client mishandled responses to 'Expect: 100-continue' headers, which could lead to a denial of service.