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

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

このコミットは、Goランタイムのパニック処理に関連するsrc/pkg/runtime/panic.cファイル内のコメントの修正と改善を目的としています。具体的には、runtime·panic関数内のコメントの記述をより正確にし、到達不能なコードパスにruntime·exit(1)を追加することで、コードの意図を明確にしています。

コミット

commit 7e0dac08c7f8948423135d05c085f076cce9ec6d
Author: Dmitriy Vyukov <dvyukov@google.com>
Date:   Thu Feb 27 20:27:55 2014 +0400

    runtime: fix and improve comments
    
    LGTM=r
    R=golang-codereviews, r
    CC=golang-codereviews, iant, khr, rsc
    https://golang.org/cl/67460043

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

https://github.com/golang/go/commit/7e0dac08c7f8948423135d05c085f076cce9ec6d

元コミット内容

runtime: fix and improve comments

変更の背景

このコミットの背景は、Goランタイムのパニック処理におけるコメントの正確性を向上させることにあります。Goのランタイムは非常に低レベルなC言語(GoのランタイムはC言語とGo言語のハイブリッドで書かれています)で書かれており、その動作は複雑です。特にパニックやdeferのような例外処理に近いメカニズムは、スタックの巻き戻しやゴルーチンの状態変更を伴うため、コードの理解を助ける正確なコメントが不可欠です。

元のコメントg->ispanic = true; // rock for newstack, where reflect.newstackcall ends upは、newstackという記述が曖昧であり、reflect.newstackcallという記述も正確ではありませんでした。Goランタイム内部では、runtime·newstackruntime·newstackcallといったシンボルが使われます。このコミットは、これらのシンボル名を正確に記述することで、コメントの意図をより明確にすることを目的としています。

また、runtime·dopanic(0);の後にruntime·exit(1);が追加されていますが、これはruntime·dopanicが通常は戻らない(プログラムを終了させる)関数であるため、その後のコードは到達不能であることを明示するためのものです。このような到達不能なコードパスを明示することは、コンパイラ最適化のヒントになったり、将来のコード変更時に誤って到達可能にしてしまうことを防ぐのに役立ちます。

前提知識の解説

Goランタイム

Goランタイムは、Goプログラムの実行を管理する低レベルなシステムです。ガベージコレクション、スケジューリング、メモリ管理、パニック処理など、Go言語の並行性モデルと効率的な実行を支える多くの機能を提供します。Goランタイムの多くの部分はGo言語で書かれていますが、一部の非常に低レベルな部分(特にOSとのインタラクションやアセンブリ言語が必要な部分)はC言語やアセンブリ言語で書かれています。

パニック (Panic) とリカバリー (Recover)

Go言語には、例外処理のメカニズムとして「パニック」と「リカバリー」があります。

  • パニック: プログラムの実行中に回復不可能なエラーが発生した場合に、現在のゴルーチンを停止させ、defer関数を実行しながらスタックを巻き戻していくメカニズムです。パニックが発生すると、通常はプログラム全体が終了します。
  • リカバリー: recover組み込み関数をdefer関数内で呼び出すことで、パニックからの回復を試みることができます。recoverが非nilの値を返した場合、パニックは捕捉され、プログラムの実行は継続されます。

Defer文

defer文は、そのdefer文を含む関数がリターンする直前(パニックが発生した場合も含む)に実行される関数呼び出しをスケジュールします。これはリソースの解放(ファイルのクローズ、ロックの解除など)や、パニックからのリカバリーによく使用されます。defer関数はLIFO(後入れ先出し)の順序で実行されます。

ゴルーチン (Goroutine)

ゴルーチンはGo言語における軽量な実行スレッドです。数千、数万のゴルーチンを同時に実行しても、OSのスレッドを直接使うよりもはるかに少ないリソースで済みます。各ゴルーチンは独自のスタックを持ち、Goランタイムのスケジューラによって管理されます。

g (Goroutine) 構造体

Goランタイム内部では、各ゴルーチンはgという構造体で表現されます。この構造体には、ゴルーチンのスタック情報、現在の状態、パニック情報、defer情報など、ゴルーチンの実行に必要なあらゆる情報が含まれています。

runtime·newstackruntime·newstackcall

これらはGoランタイム内部の関数で、スタックの管理に関連しています。

  • runtime·newstack: 新しいスタックを割り当てたり、既存のスタックを拡張したりする際に呼び出される可能性があります。
  • runtime·newstackcall: 特定の関数呼び出しを新しいスタックコンテキストで実行するためのメカニズムに関連している可能性があります。特に、reflectパッケージなど、Goのコードから低レベルなスタック操作が必要な場合に利用されることがあります。

runtime·dopanicruntime·exit

  • runtime·dopanic: パニック処理の最終段階で呼び出されるランタイム関数です。通常、この関数が呼び出されると、プログラムは終了します。
  • runtime·exit: プログラムを終了させるためのランタイム関数です。引数として終了コードを受け取ります。

技術的詳細

このコミットは、src/pkg/runtime/panic.cファイル内のruntime·panic関数に焦点を当てています。この関数は、Goプログラムでパニックが発生した際に呼び出されるGoランタイムのコアな部分です。

変更点は大きく2つあります。

  1. コメントの修正:

    • 変更前: g->ispanic = true; // rock for newstack, where reflect.newstackcall ends up
    • 変更後: g->ispanic = true; // rock for runtime·newstack, where runtime·newstackcall ends up この修正は、コメント内のnewstackという一般的な記述を、Goランタイム内部で実際に使用されるシンボル名であるruntime·newstackに修正しています。同様に、reflect.newstackcallruntime·newstackcallに修正されています。これにより、コメントが指し示す対象がより明確になり、ランタイムの内部実装を理解する上で混乱を避けることができます。g->ispanic = trueは、現在のゴルーチンがパニック状態にあることを示すフラグであり、スタックの巻き戻しやdefer関数の実行中にこの状態が利用されます。
  2. 到達不能コードの明示:

    • 変更前: runtime·dopanic(0);
    • 変更後: runtime·dopanic(0); // should not return runtime·exit(1); // not reached runtime·dopanic(0)は、Goランタイムがパニック処理を完了し、通常はプログラムを終了させる関数です。したがって、この関数が戻ることはありません。変更後のコードでは、// should not returnというコメントでその性質を明示し、さらにその後にruntime·exit(1); // not reachedという行を追加しています。これは、runtime·dopanicが戻らないため、このruntime·exit(1)の行は決して実行されないことをコードとコメントの両方で明確に示しています。このような記述は、コードの意図を明確にするだけでなく、コンパイラがこの部分を最適化する際のヒントにもなり得ます。また、将来的にruntime·dopanicの挙動が変更された場合に、このruntime·exit(1)の行が到達可能になってしまうことで、意図しないプログラム終了が発生する可能性を早期に発見する手がかりにもなります。

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

--- a/src/pkg/runtime/panic.c
+++ b/src/pkg/runtime/panic.c
@@ -226,7 +226,7 @@ runtime·panic(Eface e)
 			break;
 		// take defer off list in case of recursive panic
 		g->defer = d->link;
-		g->ispanic = true;	// rock for newstack, where reflect.newstackcall ends up
+		g->ispanic = true;	// rock for runtime·newstack, where runtime·newstackcall ends up
 		argp = d->argp;
 		pc = d->pc;
 		runtime·newstackcall(d->fn, (byte*)d->args, d->siz);
@@ -246,7 +246,8 @@ runtime·panic(Eface e)
 	// ran out of deferred calls - old-school panic now
 	runtime·startpanic();
 	printpanics(g->panic);
-	runtime·dopanic(0);
+	runtime·dopanic(0);	// should not return
+	runtime·exit(1);	// not reached
 }
 
 // Unwind the stack after a deferred function calls recover

コアとなるコードの解説

1. g->ispanic のコメント修正

-		g->ispanic = true;	// rock for newstack, where reflect.newstackcall ends up
+		g->ispanic = true;	// rock for runtime·newstack, where runtime·newstackcall ends up

この行は、現在のゴルーチンgがパニック状態であることを示すispanicフラグをtrueに設定しています。コメントは、このフラグがruntime·newstack(スタックの再構築や拡張を行うランタイム関数)やruntime·newstackcall(特定の関数を新しいスタックコンテキストで呼び出すランタイム関数)の処理において重要な役割を果たすことを説明しています。元のコメントのnewstackreflect.newstackcallは、Goランタイム内部の実際のシンボル名と異なっていたため、より正確なruntime·newstackruntime·newstackcallに修正されました。これにより、Goランタイムの低レベルな動作を追跡する開発者にとって、コメントの正確性が向上します。

2. runtime·dopanic の後のコード追加

 	printpanics(g->panic);
-	runtime·dopanic(0);
+	runtime·dopanic(0);	// should not return
+	runtime·exit(1);	// not reached

runtime·dopanic(0)は、パニック処理の最終段階で呼び出され、通常はプログラムを終了させる関数です。この関数が戻ることは想定されていません。

  • // should not return: このコメントは、runtime·dopanic(0)が呼び出し元に戻らないことを明示しています。
  • runtime·exit(1); // not reached: この行は、runtime·dopanic(0)が戻らないため、決して実行されないコードであることを示しています。runtime·exit(1)は、プログラムを終了コード1で終了させる関数です。この「到達不能」なコードを明示的に記述することで、コードの意図がより明確になり、将来の変更やデバッグの際に役立ちます。例えば、もし将来的にruntime·dopanicの挙動が変更され、何らかの理由で戻るようになった場合、このruntime·exit(1)が実行されてしまうことで、意図しないプログラム終了が発生する可能性を早期に検出できます。

関連リンク

参考にした情報源リンク

  • Go Gerrit Code Review: https://go-review.googlesource.com/
  • Go言語のソースコード: https://github.com/golang/go
  • Go言語のパニックとリカバリーに関するブログ記事やドキュメント(一般的な知識として)
  • Goランタイムの内部構造に関する情報(一般的な知識として)
  • runtime·newstackruntime·newstackcallに関するGoランタイムのソースコード分析(一般的な知識として)
  • runtime·dopanicruntime·exitに関するGoランタイムのソースコード分析(一般的な知識として)```markdown

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

このコミットは、Goランタイムのパニック処理に関連するsrc/pkg/runtime/panic.cファイル内のコメントの修正と改善を目的としています。具体的には、runtime·panic関数内のコメントの記述をより正確にし、到達不能なコードパスにruntime·exit(1)を追加することで、コードの意図を明確にしています。

コミット

commit 7e0dac08c7f8948423135d05c085f076cce9ec6d
Author: Dmitriy Vyukov <dvyukov@google.com>
Date:   Thu Feb 27 20:27:55 2014 +0400

    runtime: fix and improve comments
    
    LGTM=r
    R=golang-codereviews, r
    CC=golang-codereviews, iant, khr, rsc
    https://golang.org/cl/67460043

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

https://github.com/golang/go/commit/7e0dac08c7f8948423135d05c085f076cce9ec6d

元コミット内容

runtime: fix and improve comments

変更の背景

このコミットの背景は、Goランタイムのパニック処理におけるコメントの正確性を向上させることにあります。Goのランタイムは非常に低レベルなC言語(GoのランタイムはC言語とGo言語のハイブリッドで書かれています)で書かれており、その動作は複雑です。特にパニックやdeferのような例外処理に近いメカニズムは、スタックの巻き戻しやゴルーチンの状態変更を伴うため、コードの理解を助ける正確なコメントが不可欠です。

元のコメントg->ispanic = true; // rock for newstack, where reflect.newstackcall ends upは、newstackという記述が曖昧であり、reflect.newstackcallという記述も正確ではありませんでした。Goランタイム内部では、runtime·newstackruntime·newstackcallといったシンボルが使われます。このコミットは、これらのシンボル名を正確に記述することで、コメントの意図をより明確にすることを目的としています。

また、runtime·dopanic(0);の後にruntime·exit(1);が追加されていますが、これはruntime·dopanicが通常は戻らない(プログラムを終了させる)関数であるため、その後のコードは到達不能であることを明示するためのものです。このような到達不能なコードパスを明示することは、コンパイラ最適化のヒントになったり、将来のコード変更時に誤って到達可能にしてしまうことを防ぐのに役立ちます。

前提知識の解説

Goランタイム

Goランタイムは、Goプログラムの実行を管理する低レベルなシステムです。ガベージコレクション、スケジューリング、メモリ管理、パニック処理など、Go言語の並行性モデルと効率的な実行を支える多くの機能を提供します。Goランタイムの多くの部分はGo言語で書かれていますが、一部の非常に低レベルな部分(特にOSとのインタラクションやアセンブリ言語が必要な部分)はC言語やアセンブリ言語で書かれています。

パニック (Panic) とリカバリー (Recover)

Go言語には、例外処理のメカニズムとして「パニック」と「リカバリー」があります。

  • パニック: プログラムの実行中に回復不可能なエラーが発生した場合に、現在のゴルーチンを停止させ、defer関数を実行しながらスタックを巻き戻していくメカニズムです。パニックが発生すると、通常はプログラム全体が終了します。
  • リカバリー: recover組み込み関数をdefer関数内で呼び出すことで、パニックからの回復を試みることができます。recoverが非nilの値を返した場合、パニックは捕捉され、プログラムの実行は継続されます。

Defer文

defer文は、そのdefer文を含む関数がリターンする直前(パニックが発生した場合も含む)に実行される関数呼び出しをスケジュールします。これはリソースの解放(ファイルのクローズ、ロックの解除など)や、パニックからのリカバリーによく使用されます。defer関数はLIFO(後入れ先出し)の順序で実行されます。

ゴルーチン (Goroutine)

ゴルーチンはGo言語における軽量な実行スレッドです。数千、数万のゴルーチンを同時に実行しても、OSのスレッドを直接使うよりもはるかに少ないリソースで済みます。各ゴルーチンは独自のスタックを持ち、Goランタイムのスケジューラによって管理されます。

g (Goroutine) 構造体

Goランタイム内部では、各ゴルーチンはgという構造体で表現されます。この構造体には、ゴルーチンのスタック情報、現在の状態、パニック情報、defer情報など、ゴルーチンの実行に必要なあらゆる情報が含まれています。

runtime·newstackruntime·newstackcall

これらはGoランタイム内部の関数で、スタックの管理に関連しています。

  • runtime·newstack: 新しいスタックを割り当てたり、既存のスタックを拡張したりする際に呼び出される可能性があります。
  • runtime·newstackcall: 特定の関数呼び出しを新しいスタックコンテキストで実行するためのメカニズムに関連している可能性があります。特に、reflectパッケージなど、Goのコードから低レベルなスタック操作が必要な場合に利用されることがあります。

runtime·dopanicruntime·exit

  • runtime·dopanic: パニック処理の最終段階で呼び出されるランタイム関数です。通常、この関数が呼び出されると、プログラムは終了します。
  • runtime·exit: プログラムを終了させるためのランタイム関数です。引数として終了コードを受け取ります。

技術的詳細

このコミットは、src/pkg/runtime/panic.cファイル内のruntime·panic関数に焦点を当てています。この関数は、Goプログラムでパニックが発生した際に呼び出されるGoランタイムのコアな部分です。

変更点は大きく2つあります。

  1. コメントの修正:

    • 変更前: g->ispanic = true; // rock for newstack, where reflect.newstackcall ends up
    • 変更後: g->ispanic = true; // rock for runtime·newstack, where runtime·newstackcall ends up この修正は、コメント内のnewstackという一般的な記述を、Goランタイム内部で実際に使用されるシンボル名であるruntime·newstackに修正しています。同様に、reflect.newstackcallruntime·newstackcallに修正されています。これにより、コメントが指し示す対象がより明確になり、ランタイムの内部実装を理解する上で混乱を避けることができます。g->ispanic = trueは、現在のゴルーチンがパニック状態にあることを示すフラグであり、スタックの巻き戻しやdefer関数の実行中にこの状態が利用されます。
  2. 到達不能コードの明示:

    • 変更前: runtime·dopanic(0);
    • 変更後: runtime·dopanic(0); // should not return runtime·exit(1); // not reached runtime·dopanic(0)は、Goランタイムがパニック処理を完了し、通常はプログラムを終了させる関数です。したがって、この関数が戻ることはありません。変更後のコードでは、// should not returnというコメントでその性質を明示し、さらにその後にruntime·exit(1); // not reachedという行を追加しています。これは、runtime·dopanicが戻らないため、このruntime·exit(1)の行は決して実行されないことをコードとコメントの両方で明確に示しています。このような記述は、コードの意図を明確にするだけでなく、コンパイラがこの部分を最適化する際のヒントにもなり得ます。また、将来的にruntime·dopanicの挙動が変更された場合に、このruntime·exit(1)の行が到達可能になってしまうことで、意図しないプログラム終了が発生する可能性を早期に発見する手がかりにもなります。

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

--- a/src/pkg/runtime/panic.c
+++ b/src/pkg/runtime/panic.c
@@ -226,7 +226,7 @@ runtime·panic(Eface e)
 			break;
 		// take defer off list in case of recursive panic
 		g->defer = d->link;
-		g->ispanic = true;	// rock for newstack, where reflect.newstackcall ends up
+		g->ispanic = true;	// rock for runtime·newstack, where runtime·newstackcall ends up
 		argp = d->argp;
 		pc = d->pc;
 		runtime·newstackcall(d->fn, (byte*)d->args, d->siz);
@@ -246,7 +246,8 @@ runtime·panic(Eface e)
 	// ran out of deferred calls - old-school panic now
 	runtime·startpanic();
 	printpanics(g->panic);
-	runtime·dopanic(0);
+	runtime·dopanic(0);	// should not return
+	runtime·exit(1);	// not reached
 }
 
 // Unwind the stack after a deferred function calls recover

コアとなるコードの解説

1. g->ispanic のコメント修正

-		g->ispanic = true;	// rock for newstack, where reflect.newstackcall ends up
+		g->ispanic = true;	// rock for runtime·newstack, where runtime·newstackcall ends up

この行は、現在のゴルーチンgがパニック状態であることを示すispanicフラグをtrueに設定しています。コメントは、このフラグがruntime·newstack(スタックの再構築や拡張を行うランタイム関数)やruntime·newstackcall(特定の関数を新しいスタックコンテキストで呼び出すランタイム関数)の処理において重要な役割を果たすことを説明しています。元のコメントのnewstackreflect.newstackcallは、Goランタイム内部の実際のシンボル名と異なっていたため、より正確なruntime·newstackruntime·newstackcallに修正されました。これにより、Goランタイムの低レベルな動作を追跡する開発者にとって、コメントの正確性が向上します。

2. runtime·dopanic の後のコード追加

 	printpanics(g->panic);
-	runtime·dopanic(0);
+	runtime·dopanic(0);	// should not return
+	runtime·exit(1);	// not reached

runtime·dopanic(0)は、パニック処理の最終段階で呼び出され、通常はプログラムを終了させる関数です。この関数が戻ることは想定されていません。

  • // should not return: このコメントは、runtime·dopanic(0)が呼び出し元に戻らないことを明示しています。
  • runtime·exit(1); // not reached: この行は、runtime·dopanic(0)が戻らないため、決して実行されないコードであることを示しています。runtime·exit(1)は、プログラムを終了コード1で終了させる関数です。この「到達不能」なコードを明示的に記述することで、コードの意図がより明確になり、将来の変更やデバッグの際に役立ちます。例えば、もし将来的にruntime·dopanicの挙動が変更され、何らかの理由で戻るようになった場合、このruntime·exit(1)が実行されてしまうことで、意図しないプログラム終了が発生する可能性を早期に検出できます。

関連リンク

参考にした情報源リンク

  • Go Gerrit Code Review: https://go-review.googlesource.com/
  • Go言語のソースコード: https://github.com/golang/go
  • Go言語のパニックとリカバリーに関するブログ記事やドキュメント(一般的な知識として)
  • Goランタイムの内部構造に関する情報(一般的な知識として)
  • runtime·newstackruntime·newstackcallに関するGoランタイムのソースコード分析(一般的な知識として)
  • runtime·dopanicruntime·exitに関するGoランタイムのソースコード分析(一般的な知識として)