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

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

このコミットは、Go言語のsyscallパッケージにおけるPrlimit関数のエクスポート状態を修正するものです。具体的には、誤ってエクスポートされていたPrlimit関数を非エクスポート(内部関数)に変更しています。

コミット

commit 36fe436cbac4d2a55d06063de966798fc2216156
Author: Han-Wen Nienhuys <hanwen@google.com>
Date:   Tue Jul 31 08:21:24 2012 +1000

    pkg/syscall: unexport Prlimit.
    
    This syscall was inadvertently exported when fixing
    Getrlimit/Setrlimit on 32-bit platforms.
    
    R=golang-dev, minux.ma
    CC=golang-dev
    https://golang.org/cl/6458051

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

https://github.com/golang/go/commit/36fe436cbac4d2a55d06063de966798fc2216156

元コミット内容

pkg/syscall: unexport Prlimit. This syscall was inadvertently exported when fixing Getrlimit/Setrlimit on 32-bit platforms.

変更の背景

このコミットの背景には、Go言語のsyscallパッケージにおけるGetrlimitおよびSetrlimit関数の32ビットプラットフォームでの修正があります。以前の修正作業中に、Prlimitというシステムコールをラップする関数が意図せずエクスポート(外部からアクセス可能)されてしまいました。Go言語の慣習として、パッケージ内部でのみ使用されるべき関数は非エクスポート(小文字で始まる名前)にするべきであり、このPrlimit関数もその原則に従うべきでした。

Prlimitは、特定のプロセス(pid)のリソース制限(rlimit)を取得または設定するためのシステムコールです。GetrlimitSetrlimitは、現在のプロセス(pid=0)のリソース制限を操作するための高レベルな関数であり、内部的にPrlimitを利用することがあります。しかし、Prlimit自体は、Goのユーザーが直接呼び出すことを意図したものではなく、GetrlimitSetrlimitのようなより抽象化されたインターフェースを通じて利用されるべきでした。

このコミットは、この「意図しないエクスポート」を修正し、Goのパッケージ設計原則とAPIの整合性を保つことを目的としています。

前提知識の解説

1. Go言語におけるエクスポートと非エクスポート

Go言語では、識別子(変数、関数、型など)の最初の文字が大文字である場合、その識別子はパッケージの外部からアクセス可能(エクスポートされる)になります。一方、最初の文字が小文字である場合、その識別子はパッケージ内部でのみアクセス可能(非エクスポートされる)です。このルールは、APIの公開範囲を制御し、パッケージの内部実装の詳細を隠蔽するために非常に重要です。

2. syscallパッケージ

syscallパッケージは、Goプログラムからオペレーティングシステム(OS)のシステムコールを直接呼び出すための低レベルなインターフェースを提供します。これにより、ファイル操作、プロセス管理、ネットワーク通信など、OSカーネルが提供する機能にアクセスできます。システムコールはOSによって提供される機能であり、通常はC言語のライブラリ(例: glibc)を介して利用されますが、GoのsyscallパッケージはGoのコードから直接これらのシステムコールを呼び出すためのラッパーを提供します。

3. rlimit (リソース制限)

rlimitは、Unix系OSにおいてプロセスが利用できるシステムリソース(例: オープンできるファイルの最大数、利用できるCPU時間、メモリ量など)に上限を設定するための仕組みです。各リソースには「ソフトリミット」と「ハードリミット」の2つの制限があります。

  • ソフトリミット: プロセスが実際に利用できる上限。プロセスはこの制限をハードリミット以下であれば引き上げることができます。
  • ハードリミット: ソフトリミットの最大値。スーパーユーザーのみがハードリミットを引き上げることができます。

これらの制限は、システム全体の安定性を保ち、特定のプロセスがリソースを過剰に消費するのを防ぐために重要です。

4. GetrlimitSetrlimit システムコール

  • getrlimit(2): 現在のプロセスのリソース制限を取得するためのシステムコール。
  • setrlimit(2): 現在のプロセスのリソース制限を設定するためのシステムコール。

これらのシステムコールは、通常、現在のプロセス自身のリソース制限を操作するために使用されます。

5. prlimit(2) システムコール

prlimit(2) (または prlimit64(2) on Linux) は、getrlimitsetrlimitのより汎用的なバージョンです。これは、特定のプロセスID (pid) を指定して、そのプロセスのリソース制限を取得または設定することができます。pidが0の場合、呼び出し元のプロセスのリソース制限を操作します。このシステムコールは、Linuxカーネル2.6.36以降で利用可能です。

技術的詳細

このコミットは、Goのsyscallパッケージ内でPrlimitという名前でエクスポートされていた関数を、prlimitという非エクスポート名に変更することで、その公開範囲を制限しています。

Goのsyscallパッケージは、OSのシステムコールをGoの関数としてラップしています。これらのラッパー関数は、通常、//sysまたは//sysnbという特殊なコメントでマークされ、zsyscall_linux_*.goのようなファイルに自動生成されるコードの一部となります。

元のコードでは、Prlimit関数がSYS_PRLIMIT64システムコールを呼び出すように定義されており、その名前がPrlimit(大文字始まり)であったため、パッケージ外部からアクセス可能でした。しかし、GetrlimitSetrlimitのような高レベルな関数が内部的にPrlimitを利用するだけであり、ユーザーが直接Prlimitを呼び出す必要はないという設計意図がありました。

この変更により、Prlimitprlimitにリネームされ、Goの命名規則に従って非エクスポート関数となりました。これにより、syscallパッケージの外部からはprlimit関数に直接アクセスできなくなり、APIのクリーンさとカプセル化が向上します。

また、この変更は、syscall_linux_386.gosyscall_linux_arm.go内のGetrlimitおよびSetrlimit関数が、内部的にPrlimitではなくprlimitを呼び出すように修正されています。これは、Prlimitが非エクスポートされたことに伴う必然的な変更です。

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

このコミットでは、以下のファイルが変更されています。

  1. src/pkg/syscall/syscall_linux.go
    • //sysnb Prlimit(...) の行が //sysnb prlimit(...) に変更されています。これは、Prlimit関数が非エクスポートされることを示すためのコメントの変更です。
  2. src/pkg/syscall/syscall_linux_386.go
    • Getrlimit関数内で Prlimit の呼び出しが prlimit に変更されています。
    • Setrlimit関数内で Prlimit の呼び出しが prlimit に変更されています。
  3. src/pkg/syscall/syscall_linux_arm.go
    • Getrlimit関数内で Prlimit の呼び出しが prlimit に変更されています。
    • Setrlimit関数内で Prlimit の呼び出しが prlimit に変更されています。
  4. src/pkg/syscall/zsyscall_linux_386.go
    • 自動生成されたPrlimit関数の定義がprlimitに変更されています。
  5. src/pkg/syscall/zsyscall_linux_amd64.go
    • 自動生成されたPrlimit関数の定義がprlimitに変更されています。
  6. src/pkg/syscall/zsyscall_linux_arm.go
    • 自動生成されたPrlimit関数の定義がprlimitに変更されています。

コアとなるコードの解説

変更の核心は、Prlimitという関数名をprlimitに変更することです。

src/pkg/syscall/syscall_linux.go の変更:

--- a/src/pkg/syscall/syscall_linux.go
+++ b/src/pkg/syscall/syscall_linux.go
@@ -839,7 +839,7 @@ func Mount(source string, target string, fstype string, uintptr, data stri
 //sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
 //sys	Pause() (err error)
 //sys	PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
-//sysnb Prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
+//sysnb prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
 //sys	Read(fd int, p []byte) (n int, err error)
 //sys	Readlink(path string, buf []byte) (n int, err error)
 //sys	Rename(oldpath string, newpath string) (err error)

この変更は、Prlimit関数がsyscallパッケージの内部関数として扱われるべきであることを、コード生成ツールに指示するためのものです。//sysnbコメントは、この行がシステムコールラッパーを生成するための指示であることを示しています。Prlimitからprlimitへの変更は、Goの命名規則に従い、この関数がパッケージ外部に公開されないことを意味します。

src/pkg/syscall/syscall_linux_386.go および src/pkg/syscall/syscall_linux_arm.go の変更:

--- a/src/pkg/syscall/syscall_linux_386.go
+++ b/src/pkg/syscall/syscall_linux_386.go
@@ -78,7 +78,7 @@ const rlimInf32 = ^uint32(0)
 const rlimInf64 = ^uint64(0)
 
 func Getrlimit(resource int, rlim *Rlimit) (err error) {
-\terr = Prlimit(0, resource, rlim, nil)
+\terr = prlimit(0, resource, rlim, nil)
 \tif err != ENOSYS {
 \t\treturn err
 \t}
@@ -106,7 +106,7 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
 //sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
 
 func Setrlimit(resource int, rlim *Rlimit) (err error) {
-\terr = Prlimit(0, resource, nil, rlim)
+\terr = prlimit(0, resource, nil, rlim)
 \tif err != ENOSYS {
 \t\treturn err
 \t}

これらの変更は、GetrlimitSetrlimit関数が、非エクスポートされたprlimit関数を呼び出すように修正されたことを示しています。これは、Prlimitが非エクスポートされた結果として必要な変更であり、これらの高レベル関数が引き続き正しく機能することを保証します。

src/pkg/syscall/zsyscall_linux_386.gosrc/pkg/syscall/zsyscall_linux_amd64.gosrc/pkg/syscall/zsyscall_linux_arm.go の変更:

--- a/src/pkg/syscall/zsyscall_linux_386.go
+++ b/src/pkg/syscall/zsyscall_linux_386.go
@@ -598,7 +598,7 @@ func PivotRoot(newroot string, putold string) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
 	_, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
 	if e1 != 0 {
 		err = e1

これらのファイルは、syscall_linux.go//sysnbコメントに基づいて自動生成されるシステムコールラッパーの実装を含んでいます。Prlimitからprlimitへの関数名の変更は、これらの自動生成されたファイルにも反映され、実際のシステムコール呼び出しを行うGoの関数が非エクスポートされることを保証します。

全体として、このコミットはGoのAPI設計原則に従い、パッケージの内部実装の詳細を適切にカプセル化することで、コードの保守性と堅牢性を向上させています。

関連リンク

  • Go言語のsyscallパッケージのドキュメント: https://pkg.go.dev/syscall
  • getrlimit(2) manページ: man 2 getrlimit (Linuxシステムで実行)
  • setrlimit(2) manページ: man 2 setrlimit (Linuxシステムで実行)
  • prlimit(2) manページ: man 2 prlimit (Linuxシステムで実行)

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Linux man-pages project
  • GitHubのGoリポジトリのコミット履歴
  • Goのコードレビューシステム (Gerrit) のCL (Change List) ページ: https://golang.org/cl/6458051
  • Go言語の命名規則に関する情報 (例: Effective Go)

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

このコミットは、Go言語のsyscallパッケージにおいて、誤ってエクスポートされていたPrlimit関数を非エクスポート(内部関数)に変更するものです。これにより、Goのパッケージ設計原則とAPIの整合性が保たれます。

コミット

commit 36fe436cbac4d2a55d06063de966798fc2216156
Author: Han-Wen Nienhuys <hanwen@google.com>
Date:   Tue Jul 31 08:21:24 2012 +1000

    pkg/syscall: unexport Prlimit.
    
    This syscall was inadvertently exported when fixing
    Getrlimit/Setrlimit on 32-bit platforms.
    
    R=golang-dev, minux.ma
    CC=golang-dev
    https://golang.org/cl/6458051

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

https://github.com/golang/go/commit/36fe436cbac4d2a55d06063de966798fc2216156

元コミット内容

pkg/syscall: unexport Prlimit. This syscall was inadvertently exported when fixing Getrlimit/Setrlimit on 32-bit platforms.

変更の背景

このコミットの背景には、Go言語のsyscallパッケージにおけるGetrlimitおよびSetrlimit関数の32ビットプラットフォームでの修正作業があります。以前の修正中に、Prlimitというシステムコールをラップする関数が意図せずエクスポート(外部からアクセス可能)されてしまいました。Go言語の慣習として、パッケージ内部でのみ使用されるべき関数は非エクスポート(小文字で始まる名前)にするべきであり、このPrlimit関数もその原則に従うべきでした。

Prlimitは、特定のプロセス(pid)のリソース制限(rlimit)を取得または設定するためのシステムコールです。GetrlimitSetrlimitは、現在のプロセス(pid=0)のリソース制限を操作するための高レベルな関数であり、内部的にPrlimitを利用することがあります。しかし、Prlimit自体は、Goのユーザーが直接呼び出すことを意図したものではなく、GetrlimitSetrlimitのようなより抽象化されたインターフェースを通じて利用されるべきでした。

このコミットは、この「意図しないエクスポート」を修正し、Goのパッケージ設計原則とAPIの整合性を保つことを目的としています。

前提知識の解説

1. Go言語におけるエクスポートと非エクスポート

Go言語では、識別子(変数、関数、型など)の最初の文字が大文字である場合、その識別子はパッケージの外部からアクセス可能(エクスポートされる)になります。一方、最初の文字が小文字である場合、その識別子はパッケージ内部でのみアクセス可能(非エクスポートされる)です。このルールは、APIの公開範囲を制御し、パッケージの内部実装の詳細を隠蔽するために非常に重要です。

2. syscallパッケージ

syscallパッケージは、Goプログラムからオペレーティングシステム(OS)のシステムコールを直接呼び出すための低レベルなインターフェースを提供します。これにより、ファイル操作、プロセス管理、ネットワーク通信など、OSカーネルが提供する機能にアクセスできます。システムコールはOSによって提供される機能であり、通常はC言語のライブラリ(例: glibc)を介して利用されますが、GoのsyscallパッケージはGoのコードから直接これらのシステムコールを呼び出すためのラッパーを提供します。

3. rlimit (リソース制限)

rlimitは、Unix系OSにおいてプロセスが利用できるシステムリソース(例: オープンできるファイルの最大数、利用できるCPU時間、メモリ量など)に上限を設定するための仕組みです。各リソースには「ソフトリミット」と「ハードリミット」の2つの制限があります。

  • ソフトリミット: プロセスが実際に利用できる上限。プロセスはこの制限をハードリミット以下であれば引き上げることができます。
  • ハードリミット: ソフトリミットの最大値。スーパーユーザーのみがハードリミットを引き上げることができます。

これらの制限は、システム全体の安定性を保ち、特定のプロセスがリソースを過剰に消費するのを防ぐために重要です。

4. GetrlimitSetrlimit システムコール

  • getrlimit(2): 現在のプロセスのリソース制限を取得するためのシステムコール。
  • setrlimit(2): 現在のプロセスのリソース制限を設定するためのシステムコール。

これらのシステムコールは、通常、現在のプロセス自身のリソース制限を操作するために使用されます。

5. prlimit(2) システムコール

prlimit(2) (または prlimit64(2) on Linux) は、getrlimitsetrlimitのより汎用的なバージョンです。これは、特定のプロセスID (pid) を指定して、そのプロセスのリソース制限を取得または設定することができます。pidが0の場合、呼び出し元のプロセスのリソース制限を操作します。このシステムコールは、Linuxカーネル2.6.36以降で利用可能です。

技術的詳細

このコミットは、Goのsyscallパッケージ内でPrlimitという名前でエクスポートされていた関数を、prlimitという非エクスポート名に変更することで、その公開範囲を制限しています。

Goのsyscallパッケージは、OSのシステムコールをGoの関数としてラップしています。これらのラッパー関数は、通常、//sysまたは//sysnbという特殊なコメントでマークされ、zsyscall_linux_*.goのようなファイルに自動生成されるコードの一部となります。

元のコードでは、Prlimit関数がSYS_PRLIMIT64システムコールを呼び出すように定義されており、その名前がPrlimit(大文字始まり)であったため、パッケージ外部からアクセス可能でした。しかし、GetrlimitSetrlimitのような高レベルな関数が内部的にPrlimitを利用するだけであり、ユーザーが直接Prlimitを呼び出す必要はないという設計意図がありました。

この変更により、Prlimitprlimitにリネームされ、Goの命名規則に従って非エクスポート関数となりました。これにより、syscallパッケージの外部からはprlimit関数に直接アクセスできなくなり、APIのクリーンさとカプセル化が向上します。

また、この変更は、syscall_linux_386.gosyscall_linux_arm.go内のGetrlimitおよびSetrlimit関数が、内部的にPrlimitではなくprlimitを呼び出すように修正されています。これは、Prlimitが非エクスポートされたことに伴う必然的な変更です。

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

このコミットでは、以下のファイルが変更されています。

  1. src/pkg/syscall/syscall_linux.go
    • //sysnb Prlimit(...) の行が //sysnb prlimit(...) に変更されています。これは、Prlimit関数が非エクスポートされることを示すためのコメントの変更です。
  2. src/pkg/syscall/syscall_linux_386.go
    • Getrlimit関数内で Prlimit の呼び出しが prlimit に変更されています。
    • Setrlimit関数内で Prlimit の呼び出しが prlimit に変更されています。
  3. src/pkg/syscall/syscall_linux_arm.go
    • Getrlimit関数内で Prlimit の呼び出しが prlimit に変更されています。
    • Setrlimit関数内で Prlimit の呼び出しが prlimit に変更されています。
  4. src/pkg/syscall/zsyscall_linux_386.go
    • 自動生成されたPrlimit関数の定義がprlimitに変更されています。
  5. src/pkg/syscall/zsyscall_linux_amd64.go
    • 自動生成されたPrlimit関数の定義がprlimitに変更されています。
  6. src/pkg/syscall/zsyscall_linux_arm.go
    • 自動生成されたPrlimit関数の定義がprlimitに変更されています。

コアとなるコードの解説

変更の核心は、Prlimitという関数名をprlimitに変更することです。

src/pkg/syscall/syscall_linux.go の変更:

--- a/src/pkg/syscall/syscall_linux.go
+++ b/src/pkg/syscall/syscall_linux.go
@@ -839,7 +839,7 @@ func Mount(source string, target string, fstype string, uintptr, data stri
 //sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
 //sys	Pause() (err error)
 //sys	PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
-//sysnb Prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
+//sysnb prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
 //sys	Read(fd int, p []byte) (n int, err error)
 //sys	Readlink(path string, buf []byte) (n int, err error)
 //sys	Rename(oldpath string, newpath string) (err error)

この変更は、Prlimit関数がsyscallパッケージの内部関数として扱われるべきであることを、コード生成ツールに指示するためのものです。//sysnbコメントは、この行がシステムコールラッパーを生成するための指示であることを示しています。Prlimitからprlimitへの変更は、Goの命名規則に従い、この関数がパッケージ外部に公開されないことを意味します。

src/pkg/syscall/syscall_linux_386.go および src/pkg/syscall/syscall_linux_arm.go の変更:

--- a/src/pkg/syscall/syscall_linux_386.go
+++ b/src/pkg/syscall/syscall_linux_386.go
@@ -78,7 +78,7 @@ const rlimInf32 = ^uint32(0)
 const rlimInf64 = ^uint64(0)
 
 func Getrlimit(resource int, rlim *Rlimit) (err error) {
-\terr = Prlimit(0, resource, rlim, nil)
+\terr = prlimit(0, resource, rlim, nil)
 \tif err != ENOSYS {
 \t\treturn err
 \t}
@@ -106,7 +106,7 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
 //sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
 
 func Setrlimit(resource int, rlim *Rlimit) (err error) {
-\terr = Prlimit(0, resource, nil, rlim)
+\terr = prlimit(0, resource, nil, rlim)
 \tif err != ENOSYS {
 \t\treturn err
 \t}

これらの変更は、GetrlimitSetrlimit関数が、非エクスポートされたprlimit関数を呼び出すように修正されたことを示しています。これは、Prlimitが非エクスポートされた結果として必要な変更であり、これらの高レベル関数が引き続き正しく機能することを保証します。

src/pkg/syscall/zsyscall_linux_386.gosrc/pkg/syscall/zsyscall_linux_amd64.gosrc/pkg/syscall/zsyscall_linux_arm.go の変更:

--- a/src/pkg/syscall/zsyscall_linux_386.go
+++ b/src/pkg/syscall/zsyscall_linux_386.go
@@ -598,7 +598,7 @@ func PivotRoot(newroot string, putold string) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
 	_, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
 	if e1 != 0 {
 		err = e1

これらのファイルは、syscall_linux.go//sysnbコメントに基づいて自動生成されるシステムコールラッパーの実装を含んでいます。Prlimitからprlimitへの関数名の変更は、これらの自動生成されたファイルにも反映され、実際のシステムコール呼び出しを行うGoの関数が非エクスポートされることを保証します。

全体として、このコミットはGoのAPI設計原則に従い、パッケージの内部実装の詳細を適切にカプセル化することで、コードの保守性と堅牢性を向上させています。

関連リンク

  • Go言語のsyscallパッケージのドキュメント: https://pkg.go.dev/syscall
  • getrlimit(2) manページ: man 2 getrlimit (Linuxシステムで実行)
  • setrlimit(2) manページ: man 2 setrlimit (Linuxシステムで実行)
  • prlimit(2) manページ: man 2 prlimit (Linuxシステムで実行)

参考にした情報源リンク

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

このコミットは、Go言語のsyscallパッケージにおいて、誤ってエクスポートされていたPrlimit関数を非エクスポート(内部関数)に変更するものです。これにより、Goのパッケージ設計原則とAPIの整合性が保たれます。

コミット

commit 36fe436cbac4d2a55d06063de966798fc2216156
Author: Han-Wen Nienhuys <hanwen@google.com>
Date:   Tue Jul 31 08:21:24 2012 +1000

    pkg/syscall: unexport Prlimit.
    
    This syscall was inadvertently exported when fixing
    Getrlimit/Setrlimit on 32-bit platforms.
    
    R=golang-dev, minux.ma
    CC=golang-dev
    https://golang.org/cl/6458051

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

https://github.com/golang/go/commit/36fe436cbac4d2a55d06063de966798fc2216156

元コミット内容

pkg/syscall: unexport Prlimit. This syscall was inadvertently exported when fixing Getrlimit/Setrlimit on 32-bit platforms.

変更の背景

このコミットの背景には、Go言語のsyscallパッケージにおけるGetrlimitおよびSetrlimit関数の32ビットプラットフォームでの修正作業があります。以前の修正中に、Prlimitというシステムコールをラップする関数が意図せずエクスポート(外部からアクセス可能)されてしまいました。Go言語の慣習として、パッケージ内部でのみ使用されるべき関数は非エクスポート(小文字で始まる名前)にするべきであり、このPrlimit関数もその原則に従うべきでした。

Prlimitは、特定のプロセス(pid)のリソース制限(rlimit)を取得または設定するためのシステムコールです。GetrlimitSetrlimitは、現在のプロセス(pid=0)のリソース制限を操作するための高レベルな関数であり、内部的にPrlimitを利用することがあります。しかし、Prlimit自体は、Goのユーザーが直接呼び出すことを意図したものではなく、GetrlimitSetrlimitのようなより抽象化されたインターフェースを通じて利用されるべきでした。

このコミットは、この「意図しないエクスポート」を修正し、Goのパッケージ設計原則とAPIの整合性を保つことを目的としています。

前提知識の解説

1. Go言語におけるエクスポートと非エクスポート

Go言語では、識別子(変数、関数、型など)の最初の文字が大文字である場合、その識別子はパッケージの外部からアクセス可能(エクスポートされる)になります。一方、最初の文字が小文字である場合、その識別子はパッケージ内部でのみアクセス可能(非エクスポートされる)です。このルールは、APIの公開範囲を制御し、パッケージの内部実装の詳細を隠蔽するために非常に重要です。

2. syscallパッケージ

syscallパッケージは、Goプログラムからオペレーティングシステム(OS)のシステムコールを直接呼び出すための低レベルなインターフェースを提供します。これにより、ファイル操作、プロセス管理、ネットワーク通信など、OSカーネルが提供する機能にアクセスできます。システムコールはOSによって提供される機能であり、通常はC言語のライブラリ(例: glibc)を介して利用されますが、GoのsyscallパッケージはGoのコードから直接これらのシステムコールを呼び出すためのラッパーを提供します。

3. rlimit (リソース制限)

rlimitは、Unix系OSにおいてプロセスが利用できるシステムリソース(例: オープンできるファイルの最大数、利用できるCPU時間、メモリ量など)に上限を設定するための仕組みです。各リソースには「ソフトリミット」と「ハードリミット」の2つの制限があります。

  • ソフトリミット: プロセスが実際に利用できる上限。プロセスはこの制限をハードリミット以下であれば引き上げることができます。
  • ハードリミット: ソフトリミットの最大値。スーパーユーザーのみがハードリミットを引き上げることができます。

これらの制限は、システム全体の安定性を保ち、特定のプロセスがリソースを過剰に消費するのを防ぐために重要です。

4. GetrlimitSetrlimit システムコール

  • getrlimit(2): 現在のプロセスのリソース制限を取得するためのシステムコール。
  • setrlimit(2): 現在のプロセスのリソース制限を設定するためのシステムコール。

これらのシステムコールは、通常、現在のプロセス自身のリソース制限を操作するために使用されます。

5. prlimit(2) システムコール

prlimit(2) (または prlimit64(2) on Linux) は、getrlimitsetrlimitのより汎用的なバージョンです。これは、特定のプロセスID (pid) を指定して、そのプロセスのリソース制限を取得または設定することができます。pidが0の場合、呼び出し元のプロセスのリソース制限を操作します。このシステムコールは、Linuxカーネル2.6.36以降で利用可能です。

技術的詳細

このコミットは、Goのsyscallパッケージ内でPrlimitという名前でエクスポートされていた関数を、prlimitという非エクスポート名に変更することで、その公開範囲を制限しています。

Goのsyscallパッケージは、OSのシステムコールをGoの関数としてラップしています。これらのラッパー関数は、通常、//sysまたは//sysnbという特殊なコメントでマークされ、zsyscall_linux_*.goのようなファイルに自動生成されるコードの一部となります。

元のコードでは、Prlimit関数がSYS_PRLIMIT64システムコールを呼び出すように定義されており、その名前がPrlimit(大文字始まり)であったため、パッケージ外部からアクセス可能でした。しかし、GetrlimitSetrlimitのような高レベルな関数が内部的にPrlimitを利用するだけであり、ユーザーが直接Prlimitを呼び出す必要はないという設計意図がありました。

この変更により、Prlimitprlimitにリネームされ、Goの命名規則に従って非エクスポート関数となりました。これにより、syscallパッケージの外部からはprlimit関数に直接アクセスできなくなり、APIのクリーンさとカプセル化が向上します。

また、この変更は、syscall_linux_386.gosyscall_linux_arm.go内のGetrlimitおよびSetrlimit関数が、内部的にPrlimitではなくprlimitを呼び出すように修正されています。これは、Prlimitが非エクスポートされたことに伴う必然的な変更です。

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

このコミットでは、以下のファイルが変更されています。

  1. src/pkg/syscall/syscall_linux.go
    • //sysnb Prlimit(...) の行が //sysnb prlimit(...) に変更されています。これは、Prlimit関数が非エクスポートされることを示すためのコメントの変更です。
  2. src/pkg/syscall/syscall_linux_386.go
    • Getrlimit関数内で Prlimit の呼び出しが prlimit に変更されています。
    • Setrlimit関数内で Prlimit の呼び出しが prlimit に変更されています。
  3. src/pkg/syscall/syscall_linux_arm.go
    • Getrlimit関数内で Prlimit の呼び出しが prlimit に変更されています。
    • Setrlimit関数内で Prlimit の呼び出しが prlimit に変更されています。
  4. src/pkg/syscall/zsyscall_linux_386.go
    • 自動生成されたPrlimit関数の定義がprlimitに変更されています。
  5. src/pkg/syscall/zsyscall_linux_amd64.go
    • 自動生成されたPrlimit関数の定義がprlimitに変更されています。
  6. src/pkg/syscall/zsyscall_linux_arm.go
    • 自動生成されたPrlimit関数の定義がprlimitに変更されています。

コアとなるコードの解説

変更の核心は、Prlimitという関数名をprlimitに変更することです。

src/pkg/syscall/syscall_linux.go の変更:

--- a/src/pkg/syscall/syscall_linux.go
+++ b/src/pkg/syscall/syscall_linux.go
@@ -839,7 +839,7 @@ func Mount(source string, target string, fstype string, uintptr, data stri
 //sys	Nanosleep(time *Timespec, leftover *Timespec) (err error)
 //sys	Pause() (err error)
 //sys	PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
-//sysnb Prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
+//sysnb prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
 //sys	Read(fd int, p []byte) (n int, err error)
 //sys	Readlink(path string, buf []byte) (n int, err error)
 //sys	Rename(oldpath string, newpath string) (err error)

この変更は、Prlimit関数がsyscallパッケージの内部関数として扱われるべきであることを、コード生成ツールに指示するためのものです。//sysnbコメントは、この行がシステムコールラッパーを生成するための指示であることを示しています。Prlimitからprlimitへの変更は、Goの命名規則に従い、この関数がパッケージ外部に公開されないことを意味します。

src/pkg/syscall/syscall_linux_386.go および src/pkg/syscall/syscall_linux_arm.go の変更:

--- a/src/pkg/syscall/syscall_linux_386.go
+++ b/src/pkg/syscall/syscall_linux_386.go
@@ -78,7 +78,7 @@ const rlimInf32 = ^uint32(0)
 const rlimInf64 = ^uint64(0)
 
 func Getrlimit(resource int, rlim *Rlimit) (err error) {
-\terr = Prlimit(0, resource, rlim, nil)
+\terr = prlimit(0, resource, rlim, nil)
 \tif err != ENOSYS {
 \t\treturn err
 \t}
@@ -106,7 +106,7 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
 //sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
 
 func Setrlimit(resource int, rlim *Rlimit) (err error) {
-\terr = Prlimit(0, resource, nil, rlim)
+\terr = prlimit(0, resource, nil, rlim)
 \tif err != ENOSYS {
 \t\treturn err
 \t}

これらの変更は、GetrlimitSetrlimit関数が、非エクスポートされたprlimit関数を呼び出すように修正されたことを示しています。これは、Prlimitが非エクスポートされた結果として必要な変更であり、これらの高レベル関数が引き続き正しく機能することを保証します。

src/pkg/syscall/zsyscall_linux_386.gosrc/pkg/syscall/zsyscall_linux_amd64.gosrc/pkg/syscall/zsyscall_linux_arm.go の変更:

--- a/src/pkg/syscall/zsyscall_linux_386.go
+++ b/src/pkg/syscall/zsyscall_linux_386.go
@@ -598,7 +598,7 @@ func PivotRoot(newroot string, putold string) (err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
 	_, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
 	if e1 != 0 {
 		err = e1

これらのファイルは、syscall_linux.go//sysnbコメントに基づいて自動生成されるシステムコールラッパーの実装を含んでいます。Prlimitからprlimitへの関数名の変更は、これらの自動生成されたファイルにも反映され、実際のシステムコール呼び出しを行うGoの関数が非エクスポートされることを保証します。

全体として、このコミットはGoのAPI設計原則に従い、パッケージの内部実装の詳細を適切にカプセル化することで、コードの保守性と堅牢性を向上させています。

関連リンク

  • Go言語のsyscallパッケージのドキュメント: https://pkg.go.dev/syscall
  • getrlimit(2) manページ: man 2 getrlimit (Linuxシステムで実行)
  • setrlimit(2) manページ: man 2 setrlimit (Linuxシステムで実行)
  • prlimit(2) manページ: man 2 prlimit (Linuxシステムで実行)

参考にした情報源リンク