[インデックス 11444] ファイルの概要
このコミットは、Go言語の標準ライブラリos
パッケージから、プラットフォーム固有のSIGXXX
シグナル変数を削除するものです。これにより、os
パッケージの移植性が向上し、シグナルに関する定義がsyscall
パッケージに一元化されます。
コミット
commit a3fdd6e64970b87768f3aed733c6fe72c983bb3e
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Fri Jan 27 14:47:02 2012 -0800
os: remove SIGXXX signals variables.
They're not portable, and pkg os is supposed to be portable.
Fixes #2562
R=golang-dev, mikioh.mikioh, r, n13m3y3r, rsc
CC=golang-dev
https://golang.org/cl/5574078
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/a3fdd6e64970b87768f3aed733c6fe72c983bb3e
元コミット内容
os: remove SIGXXX signals variables.
They're not portable, and pkg os is supposed to be portable.
Fixes #2562
変更の背景
Go言語のos
パッケージは、オペレーティングシステムとの基本的な相互作用を提供することを目的としています。このパッケージは、ファイル操作、プロセス管理、環境変数へのアクセスなど、OSに依存する機能を提供しますが、その設計思想として「移植性 (portability)」が非常に重視されています。
このコミットが行われた2012年当時、os
パッケージ内にはSIGXXX
(例: SIGKILL
, SIGHUP
など)といったシグナル定数が直接定義されていました。これらの定数は、各オペレーティングシステム(Linux, macOS, FreeBSD, Windowsなど)によって値が異なる場合があり、また、一部のシグナルは特定のOSにしか存在しないなど、その定義自体がプラットフォームに依存していました。
このような状況は、os
パッケージの移植性という設計目標と矛盾していました。os
パッケージを利用するアプリケーションが、特定のOSにしか存在しないシグナル定数に依存してしまうと、そのアプリケーションは他のOSで動作しなくなる可能性がありました。
この問題を解決するため、シグナルに関するプラットフォーム固有の定義をos
パッケージから削除し、より低レベルでOS固有の機能を提供するsyscall
パッケージに一元化するという方針が採られました。これにより、os
パッケージはシグナルを抽象的なos.Signal
インターフェースとして扱い、具体的なシグナル値はsyscall
パッケージから取得するように変更されました。この変更は、Go言語の設計原則である「関心の分離 (separation of concerns)」にも合致しています。
コミットメッセージにある Fixes #2562
は、当時のGo言語のIssueトラッカー(おそらくGoogle Code上のもの)で報告されていた問題に対応するものです。このIssueは、os
パッケージにおけるシグナル定数の移植性に関する課題を指摘していたと考えられます。
前提知識の解説
シグナル (Signal)
オペレーティングシステムにおけるシグナルは、プロセスに対して非同期的にイベントを通知するメカニズムです。例えば、ユーザーがCtrl+Cを押すとSIGINT
シグナルが、プロセスが不正なメモリアクセスを試みるとSIGSEGV
シグナルが、プロセスが終了するとSIGCHLD
シグナルが送信されます。プロセスはこれらのシグナルを受信し、それぞれに対応する処理(シグナルハンドラ)を実行することができます。
シグナルには、以下のような種類があります。
- 標準シグナル: POSIX標準で定義されているシグナルで、多くのUnix系OSで共通して利用されます(例:
SIGINT
,SIGTERM
,SIGKILL
,SIGHUP
など)。 - リアルタイムシグナル: POSIX.1bで導入されたシグナルで、より柔軟な利用が可能です。
- OS固有のシグナル: 特定のOSにのみ存在するシグナルです。
Go言語のos
パッケージとsyscall
パッケージ
os
パッケージ: Go言語の標準ライブラリの一部で、オペレーティングシステムとの基本的な相互作用を提供します。ファイルシステム、プロセス、環境変数、シグナルなどの抽象化されたインターフェースを提供し、可能な限りプラットフォーム非依存なAPIを目指しています。syscall
パッケージ: Go言語の標準ライブラリの一部で、低レベルなシステムコールへのアクセスを提供します。このパッケージは、OS固有の定数、構造体、関数などを直接提供するため、非常にプラットフォーム依存性が高いです。通常、アプリケーション開発者が直接利用することは少なく、os
パッケージのような高レベルな抽象化されたパッケージの内部で利用されます。
移植性 (Portability)
ソフトウェアの移植性とは、ある環境で開発されたソフトウェアが、他の異なる環境でも変更なし、または最小限の変更で動作する能力を指します。Go言語は、その設計思想として高い移植性を重視しており、異なるOSやアーキテクチャで同じコードベースが動作するように設計されています。
ビルドスクリプトとMakefile
Go言語のプロジェクトでは、ビルドプロセスを自動化するためにシェルスクリプトやMakefile
が利用されることがあります。これらのスクリプトは、ソースファイルのコンパイル順序、依存関係、生成されるバイナリのパスなどを定義します。
技術的詳細
このコミットの主要な変更点は、os
パッケージが提供していたプラットフォーム固有のSIGXXX
シグナル定数を削除し、それらの参照をsyscall
パッケージの対応する定数に置き換えたことです。
具体的には、以下のファイルが削除されました。
src/pkg/os/mksignals.sh
: このシェルスクリプトは、各OSおよびアーキテクチャ(例:darwin_386
,linux_amd64
,windows_386
など)に対応するzsignal_*.go
ファイルを生成するためのメインスクリプトでした。src/pkg/os/mkunixsignals.sh
:mksignals.sh
から呼び出され、Unix系OS向けのzsignal_*.go
ファイルを生成するスクリプトでした。syscall
パッケージのzerrors_*.go
ファイル(システムコールエラーコードやシグナル定数が定義されている)を読み込み、os
パッケージ内でSIGXXX = UnixSignal(syscall.SIGXXX)
のような定数定義を生成していました。src/pkg/os/zsignal_*.go
: これらのファイルは、mksignals.sh
およびmkunixsignals.sh
によって自動生成されていたファイルです。各OS/アーキテクチャの組み合わせごとに存在し、そのプラットフォームで利用可能なSIGXXX
シグナル定数をos
パッケージの名前空間に公開していました。例えば、src/pkg/os/zsignal_darwin_386.go
にはSIGKILL = UnixSignal(syscall.SIGKILL)
のような定義が含まれていました。これらのファイルが削除されたことで、os
パッケージはもはやプラットフォーム固有のシグナル定数を直接持つことはなくなりました。
これらのファイルの削除に伴い、以下の変更が行われました。
- ビルドスクリプトの修正:
src/buildscript/*.sh
配下にある各プラットフォーム向けのビルドスクリプト(例:darwin_386.sh
,linux_amd64.sh
,windows_386.sh
など)から、zsignal_*.go
ファイルのコンパイル対象からの除外が行われました。これにより、これらのファイルがビルドプロセスに含まれなくなりました。 src/pkg/os/Makefile
の修正:os
パッケージのMakefile
から、GOFILES_
変数(各OSでコンパイルされるGoファイルのリスト)に含まれていたzsignal_$(GOOS)_$(GOARCH).go
の記述が削除されました。これはビルドスクリプトの変更と連携し、zsignal
ファイルがビルド対象から完全に除外されることを保証します。src/pkg/os/exec_posix.go
の修正:Process.Kill()
メソッド内で、SIGKILL
シグナルを送信する際に、以前はos.SIGKILL
を直接使用していましたが、これをos.UnixSignal(syscall.SIGKILL)
に置き換えました。これは、os
パッケージ内のSIGKILL
定数が削除されたため、syscall
パッケージから直接SIGKILL
の値を取得し、それをos.UnixSignal
型にキャストして利用するように変更されたことを意味します。src/pkg/os/exec_windows.go
の修正: Windows環境でのプロセスシグナル処理においても、同様にSIGKILL
の参照がsyscall.SIGKILL
に置き換えられました。switch sig.(UnixSignal) { case SIGKILL:
のようなパターンマッチングから、if us, ok := sig.(UnixSignal); ok && us == syscall.SIGKILL {
のような型アサーションと値の比較に変わっています。これは、os.SIGKILL
定数がなくなったため、UnixSignal
型にキャスト可能かを確認し、その値がsyscall.SIGKILL
と等しいかをチェックする形に変更されたものです。src/pkg/os/signal/signal_test.go
の修正: シグナルテストファイルでも、os.SIGHUP
の直接参照が削除され、const sighup = os.UnixSignal(syscall.SIGHUP)
という新しい定数が導入され、これを利用するように変更されました。これにより、テストコードも新しいシグナル参照のパターンに準拠するようになりました。
この変更により、os
パッケージはシグナルに関するプラットフォーム固有の詳細を内部に持つことをやめ、syscall
パッケージにその責任を委譲しました。os
パッケージは、os.Signal
という抽象的なインターフェースを通じてシグナルを扱い、具体的なシグナル値が必要な場合はsyscall
パッケージから取得するという、よりクリーンで移植性の高い設計になりました。
コアとなるコードの変更箇所
このコミットのコアとなる変更は、主に以下の3つの側面から見ることができます。
-
zsignal_*.go
ファイル群の削除: 各OS/アーキテクチャ固有のシグナル定数を定義していた自動生成ファイルがすべて削除されました。src/pkg/os/zsignal_darwin_386.go
src/pkg/os/zsignal_darwin_amd64.go
src/pkg/os/zsignal_freebsd_386.go
src/pkg/os/zsignal_freebsd_amd64.go
src/pkg/os/zsignal_linux_386.go
src/pkg/os/zsignal_linux_amd64.go
src/pkg/os/zsignal_linux_arm.go
src/pkg/os/zsignal_netbsd_386.go
src/pkg/os/zsignal_netbsd_amd64.go
src/pkg/os/zsignal_openbsd_386.go
src/pkg/os/zsignal_openbsd_amd64.go
src/pkg/os/zsignal_windows_386.go
src/pkg/os/zsignal_windows_amd64.go
-
シグナル生成スクリプトの削除: 上記
zsignal_*.go
ファイルを生成していたスクリプトが削除されました。src/pkg/os/mksignals.sh
src/pkg/os/mkunixsignals.sh
-
os
パッケージ内のシグナル参照の変更:os
パッケージ内で直接SIGXXX
定数を使用していた箇所が、syscall
パッケージの対応する定数に置き換えられました。-
src/pkg/os/exec_posix.go
:--- a/src/pkg/os/exec_posix.go +++ b/src/pkg/os/exec_posix.go @@ -48,7 +48,7 @@ func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err e // Kill causes the Process to exit immediately. func (p *Process) Kill() error { - return p.Signal(SIGKILL) + return p.Signal(UnixSignal(syscall.SIGKILL)) } // Exec replaces the current process with an execution of the
-
src/pkg/os/exec_windows.go
:--- a/src/pkg/os/exec_windows.go +++ b/src/pkg/os/exec_windows.go @@ -37,8 +37,7 @@ func (p *Process) Signal(sig Signal) error { if p.done { return errors.New("os: process already finished") } - switch sig.(UnixSignal) { - case SIGKILL: + if us, ok := sig.(UnixSignal); ok && us == syscall.SIGKILL { e := syscall.TerminateProcess(syscall.Handle(p.handle), 1) return NewSyscallError("TerminateProcess", e) }
-
src/pkg/os/signal/signal_test.go
:--- a/src/pkg/os/signal/signal_test.go +++ b/src/pkg/os/signal/signal_test.go @@ -12,11 +12,13 @@ import ( "testing" ) +const sighup = os.UnixSignal(syscall.SIGHUP) + func TestSignal(t *testing.T) { // Send this process a SIGHUP. syscall.Syscall(syscall.SYS_KILL, uintptr(syscall.Getpid()), syscall.SIGHUP, 0) - if sig := (<-Incoming).(os.UnixSignal); sig != os.SIGHUP { - t.Errorf("signal was %v, want %v", sig, os.SIGHUP) + if sig := (<-Incoming).(os.UnixSignal); sig != sighup { + t.Errorf("signal was %v, want %v", sig, sighup) } }
-
コアとなるコードの解説
このコミットの核心は、os
パッケージがシグナルを扱う方法の根本的な変更にあります。
以前は、os
パッケージは各プラットフォーム向けに自動生成されたzsignal_*.go
ファイルを通じて、os.SIGKILL
やos.SIGHUP
といったシグナル定数を直接公開していました。これらの定数は、内部的にはsyscall.SIGKILL
などのsyscall
パッケージの定数をos.UnixSignal
型にキャストしたものでした。
しかし、このアプローチには以下の問題がありました。
- 移植性の欠如:
zsignal_*.go
ファイルはプラットフォーム固有であり、os
パッケージの設計目標である移植性と矛盾していました。特定のOSにしか存在しないシグナルがos
パッケージのAPIとして公開される可能性がありました。 - 冗長性:
syscall
パッケージに既に存在するシグナル定数を、os
パッケージで再度定義し直すことは冗長でした。 - ビルドプロセスの複雑化:
mksignals.sh
やmkunixsignals.sh
といった自動生成スクリプトが必要となり、ビルドプロセスが複雑になっていました。
このコミットでは、これらの問題を解決するために、zsignal_*.go
ファイルとそれらを生成するスクリプトを完全に削除しました。これにより、os
パッケージはもはやSIGXXX
という名前のシグナル定数を直接公開しなくなりました。
代わりに、os
パッケージ内でシグナルを扱う必要がある箇所(例: Process.Kill()
メソッド)では、直接syscall
パッケージのシグナル定数(例: syscall.SIGKILL
)を参照し、それをos.UnixSignal
型にキャストして利用するように変更されました。
os.UnixSignal(syscall.SIGKILL)
:syscall.SIGKILL
は、syscall
パッケージで定義されている、OS固有のSIGKILL
シグナルの整数値です。これはプラットフォームによって異なる値を持つ可能性がありますが、syscall
パッケージがその差異を吸収します。os.UnixSignal
は、os
パッケージ内で定義されている型であり、syscall
パッケージのシグナル値をos
パッケージのシグナルとして扱うためのラッパーです。これにより、os
パッケージはシグナルの具体的な数値表現に依存せず、抽象的なos.Signal
インターフェースを通じてシグナルを処理できるようになります。
この変更により、os
パッケージはシグナルの具体的な数値表現から完全に分離され、シグナルに関するプラットフォーム固有の詳細はsyscall
パッケージに一元化されました。os
パッケージは、より高レベルで抽象的なシグナル処理のインターフェースを提供することに専念できるようになり、Go言語の標準ライブラリ全体の移植性と保守性が向上しました。
関連リンク
- Go言語の
os
パッケージ: https://pkg.go.dev/os - Go言語の
syscall
パッケージ: https://pkg.go.dev/syscall - Go言語のIssueトラッカー (現在のもの): https://github.com/golang/go/issues (ただし、#2562は古いIssueトラッカーに存在した可能性が高い)
参考にした情報源リンク
- コミット情報:
/home/orange/Project/comemo/commit_data/11444.txt
- GitHubコミットページ: https://github.com/golang/go/commit/a3fdd6e64970b87768f3aed733c6fe72c983bb3e
- Go言語のドキュメント (pkg.go.dev)
- Unix系OSにおけるシグナルに関する一般的な知識
- Go言語のビルドシステムに関する一般的な知識