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

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

このコミットは、Go言語のsyscallパッケージにおけるDragonFly BSD向けの変更です。具体的には、DragonFly BSD 3.6のシステムコール定義をGoの内部で利用するために、自動生成される「z-files」を更新し、F_DUPFD_CLOEXEC定数の扱いを修正しています。

コミット

commit 4e7049bb848e2e7de7ee8c187cf272ca0c0d5a38
Author: Joel Sing <jsing@google.com>
Date:   Thu Mar 6 00:09:09 2014 +1100

    syscall: regenerate z-files for dragonfly
    
    Regenerate z-files for DragonFly BSD 3.6.
    
    F_DUP_FD_CLOEXEC is now supported, so remove the zero value constant
    from types_dragonfly.go so that we use the generated value from the
    z-files.
    
    LGTM=mikioh.mikioh
    R=golang-codereviews, mikioh.mikioh
    CC=golang-codereviews
    https://golang.org/cl/70080047

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

https://github.com/golang/go/commit/4e7049bb848e2e7de7ee8c187cf272ca0c0d5a38

元コミット内容

このコミットの目的は、DragonFly BSD 3.6向けにGoのsyscallパッケージのz-filesを再生成することです。これにより、F_DUPFD_CLOEXECがサポートされるようになったため、types_dragonfly.goから手動で定義されていたゼロ値の定数を削除し、z-filesから生成される正しい値を使用するように変更しています。

変更の背景

Go言語は、様々なオペレーティングシステム(OS)やアーキテクチャをサポートするために、OS固有のシステムコールを呼び出すためのメカニズムを提供しています。このメカニズムは、syscallパッケージを通じて実現されており、各OSのシステムコール番号や定数を定義した「z-files」と呼ばれる自動生成ファイルに依存しています。

このコミットが行われた2014年3月当時、DragonFly BSDはバージョン3.6がリリースされていました。新しいOSバージョンでは、既存のシステムコールに加えて新たなシステムコールが追加されたり、既存の定数の値が変更されたりすることがあります。特に、F_DUPFD_CLOEXECというフラグは、ファイルディスクリプタの複製と同時にCLOEXECフラグを設定する機能を提供し、セキュリティと堅牢性を向上させる重要な機能です。

以前のDragonFly BSDのバージョンではF_DUPFD_CLOEXECがサポートされていなかったため、Goのsyscallパッケージではtypes_dragonfly.goファイル内でこの定数を手動で0として定義していました。しかし、DragonFly BSD 3.6でこの機能が正式にサポートされたため、Goのビルドプロセスでz-filesを再生成することで、OSが提供する正しいF_DUPFD_CLOEXECの値を取り込む必要が生じました。この変更は、GoがDragonFly BSDの最新の機能と互換性を保ち、より正確なシステムコールインターフェースを提供するために不可欠でした。

前提知識の解説

Go言語のsyscallパッケージとz-files

Go言語のsyscallパッケージは、Goプログラムから低レベルのOSシステムコールを直接呼び出すためのインターフェースを提供します。これは、ファイル操作、プロセス管理、ネットワーク通信など、OSカーネルが提供する基本的な機能にアクセスするために使用されます。

syscallパッケージは、OSやアーキテクチャに依存する部分を抽象化するために、z-filesと呼ばれる特殊なファイルを活用しています。これらのファイルは、Goのビルドプロセス中に、特定のOS(例: Linux, macOS, FreeBSD, DragonFly BSD)およびアーキテクチャ(例: amd64, 386)向けのシステムコール番号、定数、構造体定義などを自動生成して作成されます。ファイル名の先頭にzが付くのは、これらが手書きではなく自動生成されたファイルであることを示唆しています。

例えば、zerrors_dragonfly_amd64.goのようなファイルは、DragonFly BSDのamd64アーキテクチャにおけるエラーコードや定数を定義しています。これらのz-filesが存在することで、Goコンパイラは各プラットフォームに特化したシステムコールを正しく解決し、Goプログラムが異なるOS環境でも動作できるようにしています。

DragonFly BSD

DragonFly BSDは、FreeBSD 4.8からフォークしたオープンソースのUnix系オペレーティングシステムです。大規模な対称型マルチプロセッシング(SMP)システムでのパフォーマンスとスケーラビリティを向上させることを目的として開発が進められています。特に、メッセージパッシングベースのカーネル設計や、HAMMERファイルシステムなどの独自の技術が特徴です。

DragonFly BSD 3.6は、2013年11月25日にリリースされたバージョンで、主要なSMP改善、DPorts(FreeBSDのportsシステムをベースにしたパッケージ管理)のデフォルト化、実験的なIntel/AMD DRM/KMSグラフィックスドライバのサポートなど、多くの重要な機能強化が含まれていました。このバージョンアップに伴い、システムコールインターフェースにも変更や追加があったため、Goのsyscallパッケージもそれに対応する必要がありました。

F_DUPFD_CLOEXEC

F_DUPFD_CLOEXECは、Unix系OSのfcntl()システムコールで使用されるフラグの一つです。このフラグは、既存のファイルディスクリプタを複製(duplicate)し、同時に複製された新しいファイルディスクリプタにFD_CLOEXECフラグを設定する操作をアトミックに実行します。

  • ファイルディスクリプタ (File Descriptor, FD): OSがファイルやソケットなどのI/Oリソースを識別するために使用する整数値です。
  • fcntl()システムコール: ファイルディスクリプタの属性を操作するための汎用的なシステムコールです。
  • FD_CLOEXEC (Close-on-Exec): このフラグがファイルディスクリプタに設定されている場合、そのファイルディスクリプタは、execファミリーの関数(例: execve())によって新しいプログラムが実行される際に自動的に閉じられます。これにより、親プロセスが開いていたファイルディスクリプタが意図せず子プロセスに継承されることを防ぎます。これはセキュリティ上のベストプラクティスであり、リソースリークを防ぐためにも重要です。

F_DUPFD_CLOEXECの重要な利点は、アトミック性です。もしこのフラグがなければ、ファイルディスクリプタの複製とFD_CLOEXECの設定は通常、2つの別々のシステムコール(F_DUPFDによる複製と、F_SETFDによるFD_CLOEXECの設定)で行う必要があります。マルチスレッド環境では、この2つの操作の間に別のスレッドがfork()exec()を呼び出すと、複製されたファイルディスクリプタがFD_CLOEXECが設定される前に子プロセスに継承されてしまうという競合状態(race condition)が発生する可能性があります。F_DUPFD_CLOEXECは、この競合状態を回避し、常に安全にファイルディスクリプタを複製し、CLOEXECフラグを設定することを保証します。

このフラグは、Linux 2.6.24で導入され、POSIX.1-2008標準の一部となっています。

技術的詳細

このコミットの技術的な核心は、GoのsyscallパッケージがDragonFly BSDのシステムコールインターフェースの進化に追従することにあります。

Goのsyscallパッケージは、各OSのシステムコールや定数をGoのコードから利用できるようにするために、C言語のヘッダファイルやOSの内部定義から情報を抽出し、Goのソースコードとして自動生成する仕組みを持っています。この自動生成されたファイル群が「z-files」です。

DragonFly BSD 3.6では、F_DUPFD_CLOEXECという新しいfcntlコマンドが導入されました。これは、ファイルディスクリプタを複製し、同時にCLOEXECフラグを設定するアトミックな操作を可能にするものです。Goのsyscallパッケージがこの新しい定数を正しく認識し、利用するためには、z-filesを再生成して、OSが提供するこの定数の実際の値を取り込む必要がありました。

コミット前のGoのコードベースでは、F_DUPFD_CLOEXECがDragonFly BSDでサポートされていないという前提のもと、src/pkg/syscall/types_dragonfly.goファイル内でこの定数を手動で0として定義していました。これは、サポートされていない機能に対してダミーの値を割り当てる一般的な手法です。しかし、DragonFly BSD 3.6でサポートが開始されたことで、この手動定義は不要となり、むしろz-filesから生成される正しい値と競合する可能性がありました。

したがって、このコミットでは以下の2つの主要な変更が行われました。

  1. z-filesの再生成: DragonFly BSD 3.6のシステムコール定義に合わせて、zerrors_dragonfly_386.go, zerrors_dragonfly_amd64.go, zsysnum_dragonfly_386.go, zsysnum_dragonfly_amd64.go, ztypes_dragonfly_386.go, ztypes_dragonfly_amd64.goなどのz-filesが再生成されました。これにより、F_DUPFD_CLOEXECの正しい値がこれらのファイルに取り込まれました。
  2. 手動定義の削除: src/pkg/syscall/types_dragonfly.goから、手動で定義されていたF_DUPFD_CLOEXEC = 0の行が削除されました。これにより、Goコンパイラはz-filesから提供される正しいF_DUPFD_CLOEXECの値を使用するようになります。

また、zerrors_dragonfly_386.gozerrors_dragonfly_amd64.goでは、エラーコード93に対する文字列が"unknown error: 93"から"no medium found"に変更されています。これは、OSのエラーコード定義の更新に合わせたもので、より具体的なエラーメッセージを提供します。

さらに、zsysnum_dragonfly_386.gozsysnum_dragonfly_amd64.goでは、いくつかのシステムコール番号(SYS_SEMSYS, SYS_MSGSYS, SYS_SHMSYS)が削除され、新たにSYS_VMM_GUEST_CTLSYS_VMM_GUEST_SYNC_ADDRが追加されています。これは、DragonFly BSDのカーネルにおけるシステムコールテーブルの変更を反映したもので、特に仮想マシン管理に関連する新しいシステムコールが追加されたことを示しています。

これらの変更により、GoのsyscallパッケージはDragonFly BSD 3.6のシステムコールインターフェースと完全に同期され、GoプログラムがこのOS上でより安定かつ効率的に動作するようになりました。

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

このコミットで変更された主要なファイルと、その変更内容は以下の通りです。

  1. src/pkg/syscall/types_dragonfly.go:

    • F_DUPFD_CLOEXEC = 0 // not supported の定数定義が削除されました。
  2. src/pkg/syscall/zerrors_dragonfly_386.go および src/pkg/syscall/zerrors_dragonfly_amd64.go:

    • F_DUP2FD, F_DUP2FD_CLOEXEC, F_DUPFD_CLOEXEC の定数が追加され、それぞれ正しい値が割り当てられました。
    • エラーコード93のメッセージが "unknown error: 93" から "no medium found" に変更されました。
  3. src/pkg/syscall/zsysnum_dragonfly_386.go および src/pkg/syscall/zsysnum_dragonfly_amd64.go:

    • SYS_SEMSYS, SYS_MSGSYS, SYS_SHMSYS のシステムコール番号が削除されました。
    • SYS_VMM_GUEST_CTL, SYS_VMM_GUEST_SYNC_ADDR のシステムコール番号が追加されました。
  4. src/pkg/syscall/ztypes_dragonfly_386.go および src/pkg/syscall/ztypes_dragonfly_amd64.go:

    • F_DUPFD_CLOEXEC = 0 の定数定義が削除されました。

コアとなるコードの解説

src/pkg/syscall/types_dragonfly.go の変更

--- a/src/pkg/syscall/types_dragonfly.go
+++ b/src/pkg/syscall/types_dragonfly.go
@@ -98,10 +98,6 @@ type _Gid_t C.gid_t
 
 // Files
 
-const (
-	F_DUPFD_CLOEXEC = 0 // not supported
-)
-
 const ( // Directory mode bits
 	S_IFMT   = C.S_IFMT
 	S_IFIFO  = C.S_IFIFO

この変更は、F_DUPFD_CLOEXECがDragonFly BSD 3.6でサポートされるようになったため、Goのコードベースで手動で定義されていたこの定数を削除するものです。以前はサポートされていなかったため、ダミーの0が割り当てられていましたが、z-filesの再生成によりOSから正しい値が提供されるようになったため、この手動定義は冗長となり、削除されました。これにより、GoのsyscallパッケージはOSの実際の定義に依存するようになります。

src/pkg/syscall/zerrors_dragonfly_386.go および src/pkg/syscall/zerrors_dragonfly_amd64.go の変更

--- a/src/pkg/syscall/zerrors_dragonfly_386.go
+++ b/src/pkg/syscall/zerrors_dragonfly_386.go
@@ -311,7 +311,10 @@ const (
 	FD_CLOEXEC                        = 0x1
 	FD_SETSIZE                        = 0x400
 	FLUSHO                            = 0x800000
+\tF_DUP2FD                          = 0xa
+\tF_DUP2FD_CLOEXEC                  = 0x12
 	F_DUPFD                           = 0x0
+\tF_DUPFD_CLOEXEC                   = 0x11
 	F_GETFD                           = 0x1
 	F_GETFL                           = 0x3
 	F_GETLK                           = 0x7
@@ -1475,7 +1478,7 @@ var errors = [...]string{\n \t90: \"multihop attempted\",\n \t91: \"link has been severed\",\n \t92: \"protocol error\",\n-\t93: \"unknown error: 93\",\n+\t93: \"no medium found\",\n \t94: \"unknown error: 94\",\n \t95: \"unknown error: 95\",\n \t96: \"unknown error: 96\",

この差分は、z-filesが再生成された結果を示しています。

  • F_DUP2FD, F_DUP2FD_CLOEXEC, F_DUPFD_CLOEXECといった新しい定数が追加され、それぞれにDragonFly BSD 3.6で定義された実際の値(16進数)が割り当てられています。これは、OSがこれらの機能を提供するようになったことをGoが認識したことを意味します。
  • エラーコード93に対応する文字列が"unknown error: 93"から"no medium found"に変更されました。これは、OSのエラー定義が更新され、より具体的なエラーメッセージが提供されるようになったことを反映しています。

src/pkg/syscall/zsysnum_dragonfly_386.go および src/pkg/syscall/zsysnum_dragonfly_amd64.go の変更

--- a/src/pkg/syscall/zsysnum_dragonfly_386.go
+++ b/src/pkg/syscall/zsysnum_dragonfly_386.go
@@ -115,9 +115,6 @@ const (
 	SYS_UNAME         = 164 // { int uname(struct utsname *name); }\n 	SYS_SYSARCH       = 165 // { int sysarch(int op, char *parms); }\n 	SYS_RTPRIO        = 166 // { int rtprio(int function, pid_t pid, \\\n-\tSYS_SEMSYS        = 169 // { int semsys(int which, int a2, int a3, int a4, \\\n-\tSYS_MSGSYS        = 170 // { int msgsys(int which, int a2, int a3, int a4, \\\n-\tSYS_SHMSYS        = 171 // { int shmsys(int which, int a2, int a3, int a4); }\n \tSYS_EXTPREAD      = 173 // { ssize_t extpread(int fd, void *buf, \\\n \tSYS_EXTPWRITE     = 174 // { ssize_t extpwrite(int fd, const void *buf, \\\n \tSYS_NTP_ADJTIME   = 176 // { int ntp_adjtime(struct timex *tp); }\n@@ -300,4 +297,6 @@ const (\n \tSYS_LINKAT                 = 531 // { int linkat(int fd1, char *path1, int fd2, \\\n \tSYS_EACCESS                = 532 // { int eaccess(char *path, int flags); }\n \tSYS_LPATHCONF              = 533 // { int lpathconf(char *path, int name); }\n+\tSYS_VMM_GUEST_CTL          = 534 // { int vmm_guest_ctl(int op, struct vmm_guest_options *options); }\n+\tSYS_VMM_GUEST_SYNC_ADDR    = 535 // { int vmm_guest_sync_addr(long *dstaddr, long *srcaddr); }\n )

この差分もz-filesの再生成によるものです。

  • SYS_SEMSYS, SYS_MSGSYS, SYS_SHMSYSといったシステムコール番号が削除されています。これは、DragonFly BSDのカーネルがこれらのシステムコールを廃止したか、あるいはGoがこれらのシステムコールを直接利用する必要がなくなったことを示唆しています。
  • SYS_VMM_GUEST_CTLSYS_VMM_GUEST_SYNC_ADDRという新しいシステムコール番号が追加されています。これらは、DragonFly BSD 3.6で導入された仮想マシン管理(VMM)に関連する機能であり、Goがこれらの新しいOS機能と連携できるようになりました。

src/pkg/syscall/ztypes_dragonfly_386.go および src/pkg/syscall/ztypes_dragonfly_amd64.go の変更

--- a/src/pkg/syscall/ztypes_dragonfly_386.go
+++ b/src/pkg/syscall/ztypes_dragonfly_386.go
@@ -54,10 +54,6 @@ type Rlimit struct {\n 
 type _Gid_t uint32\n 
-const (\n-\tF_DUPFD_CLOEXEC = 0\n-)\n-\n const (\n \tS_IFMT   = 0xf000\n \tS_IFIFO  = 0x1000

この変更は、types_dragonfly.goと同様に、z-files内で手動で定義されていたF_DUPFD_CLOEXEC = 0の行を削除するものです。これにより、Goのsyscallパッケージは、OSが提供する正しいF_DUPFD_CLOEXECの値を使用するようになります。

これらの変更は全体として、GoのsyscallパッケージがDragonFly BSD 3.6の最新のシステムコールインターフェースと完全に同期し、GoプログラムがこのOS上でより正確かつ効率的に動作するための基盤を強化するものです。

関連リンク

参考にした情報源リンク

  • Go syscall z-filesに関するWeb検索結果
  • DragonFly BSD 3.6 featuresに関するWeb検索結果
  • F_DUPFD_CLOEXECに関するWeb検索結果
  • golang/go GitHubリポジトリ
  • golang.org/cl/70080047 (Gerrit Code Review)