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

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

このコミットは、Go言語の標準ライブラリos/signalパッケージ内のテストコードsignal_test.goにおけるログ出力の修正に関するものです。具体的には、テスト中にどのシグナルが送信されているかを正確に反映するように、t.Logfによるログメッセージが調整されています。

コミット

commit 932428a1ed5832fdb25a170e2d9b8c994cc5e72a
Author: Joel Sing <jsing@google.com>
Date:   Mon Oct 7 09:04:20 2013 -0700

    os/signal: make test logs reflect reality
    
    R=golang-dev, iant
    CC=golang-dev
    https://golang.org/cl/14470043

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

https://github.com/golang/go/commit/932428a1ed5832fdb25a170e2d9b8c994cc5e72a

元コミット内容

os/signal: make test logs reflect reality

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/14470043

変更の背景

このコミットの背景は、os/signalパッケージのテストコードsignal_test.goにおけるログ出力が、実際に送信されているシグナルと一致していなかったという単純な問題にあります。テストコードは、特定のシグナル(例: SIGHUP, SIGWINCH)をプロセスに送信し、そのシグナルが正しくos/signalパッケージによって捕捉・処理されることを検証します。

しかし、既存のログメッセージは、送信されるシグナルの種類と異なるメッセージを表示していました。例えば、SIGHUPを送信する直前に"sigwinch..."とログ出力される箇所がありました。このような不一致は、テストの実行ログを読んだ際に混乱を招き、デバッグを困難にする可能性があります。

このコミットは、テストの可読性とデバッグの容易性を向上させるために、ログメッセージを実際の動作と同期させることを目的としています。機能的な変更は一切なく、純粋にテストコードの品質改善のための修正です。

前提知識の解説

1. Go言語のos/signalパッケージ

os/signalパッケージは、Goプログラムがオペレーティングシステムからのシグナルをどのように処理するかを制御するための機能を提供します。シグナルは、プロセスに対して非同期的に発生するイベントであり、例えば以下のようなものがあります。

  • syscall.SIGHUP: ハングアップシグナル。通常、ターミナルセッションが終了した際に、そのターミナルから起動されたプロセスに送られます。デーモンプロセスでは設定ファイルの再読み込みなどに使われることがあります。
  • syscall.SIGINT: 割り込みシグナル。通常、Ctrl+Cによってプロセスに送られ、プログラムを終了させるために使われます。
  • syscall.SIGTERM: 終了シグナル。プログラムを正常に終了させるために使われます。
  • syscall.SIGKILL: 強制終了シグナル。捕捉・無視・ブロックすることができないシグナルで、プロセスを即座に終了させます。
  • syscall.SIGWINCH: ウィンドウサイズ変更シグナル。ターミナルエミュレータのウィンドウサイズが変更された際に送られます。

os/signalパッケージの主要な関数には以下のようなものがあります。

  • signal.Notify(c chan<- os.Signal, sig ...os.Signal): 指定されたシグナル(sig)を受信した際に、それらをチャネルcに転送するように設定します。sigが指定されない場合、すべてのシグナルが転送されます。
  • signal.Stop(c chan<- os.Signal): Notifyによって設定されたシグナル転送を停止します。

2. Go言語のテストフレームワーク (testingパッケージ)

Go言語には、標準でテストをサポートするtestingパッケージが用意されています。

  • func TestXxx(t *testing.T): テスト関数はTestで始まり、*testing.T型の引数を取ります。
  • t.Logf(format string, args ...interface{}): テスト中に情報をログ出力するためのメソッドです。フォーマット文字列と引数を受け取り、標準出力にメッセージを出力します。これはテストが失敗した場合でも表示され、デバッグに役立ちます。
  • syscall.Kill(pid int, sig syscall.Signal): 指定されたプロセスID (pid) に指定されたシグナル (sig) を送信するためのシステムコールです。テスト内でシグナルを生成するために使用されます。
  • syscall.Getpid(): 現在実行中のプロセスのプロセスID (PID) を取得するためのシステムコールです。

3. シグナルハンドリングの重要性

シグナルハンドリングは、堅牢なアプリケーションを構築する上で非常に重要です。適切にシグナルを処理することで、プログラムは以下のような動作を実現できます。

  • 正常終了: SIGTERMSIGINTを受信した際に、開いているファイルやネットワーク接続を閉じ、リソースを解放してから終了する。
  • 設定の再読み込み: SIGHUPを受信した際に、プログラムを再起動することなく設定ファイルを再読み込みする。
  • デバッグ情報の出力: 特定のシグナルを受信した際に、現在の状態やスタックトレースをログに出力する。

このコミットは、シグナルハンドリングのロジック自体を変更するものではなく、そのテストにおけるログの正確性を高めることで、将来的なデバッグや理解を容易にすることを目的としています。

技術的詳細

このコミットは、src/pkg/os/signal/signal_test.goファイル内のTestSignal関数に対して行われた修正です。TestSignal関数は、os/signalパッケージのNotifyおよびStop関数の動作を検証するために、様々なシグナルを現在のプロセスに送信し、それらが正しくチャネルに配信されることを確認します。

修正の核心は、t.Logf呼び出しの引数を、実際にsyscall.Killで送信されるシグナルと一致させることです。

具体的には、以下の2種類の修正が行われています。

  1. t.Logfの移動:

    • 元のコードでは、t.Logf("sighup...")Notify呼び出しの直後にあり、syscall.Kill(syscall.Getpid(), syscall.SIGHUP)の前にありました。
    • 修正後、t.Logf("sighup...")syscall.Kill(syscall.Getpid(), syscall.SIGHUP)の直前に移動されました。これにより、ログメッセージがシグナル送信の直前に出力され、よりタイムリーな情報を提供します。
  2. ログメッセージの修正:

    • SIGWINCHを送信した後に、さらに2つのSIGHUPを送信するテストセクションがありました。
    • このSIGHUP送信の直前にあるt.Logf呼び出しが、誤って"sigwinch..."と出力していました。
    • このコミットでは、これらのt.Logf("sigwinch...")t.Logf("sighup...")に修正され、実際に送信されるシグナルとログメッセージが一致するようになりました。

これらの変更は、テストの実行ログを見た際に、どのシグナルがいつ送信されたのかを正確に把握できるようにするためのものです。機能的な動作には影響を与えませんが、テストのデバッグや理解の効率を大幅に向上させます。

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

変更はsrc/pkg/os/signal/signal_test.goファイルのみです。

--- a/src/pkg/os/signal/signal_test.go
+++ b/src/pkg/os/signal/signal_test.go
@@ -36,8 +36,8 @@ func TestSignal(t *testing.T) {
 	Notify(c, syscall.SIGHUP)
 	defer Stop(c)
 
-\tt.Logf("sighup...")
 	// Send this process a SIGHUP
+\tt.Logf("sighup...")
 	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
 	waitSig(t, c, syscall.SIGHUP)
 
@@ -45,18 +45,18 @@ func TestSignal(t *testing.T) {
 	c1 := make(chan os.Signal, 1)
 	Notify(c1)
 
-\tt.Logf("sigwinch...")
 	// Send this process a SIGWINCH
+\tt.Logf("sigwinch...")
 	syscall.Kill(syscall.Getpid(), syscall.SIGWINCH)
 	waitSig(t, c1, syscall.SIGWINCH)
 
 	// Send two more SIGHUPs, to make sure that
 	// they get delivered on c1 and that not reading
 	// from c does not block everything.
-\tt.Logf("sigwinch...")
+\tt.Logf("sighup...")
 	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
 	waitSig(t, c1, syscall.SIGHUP)
-\tt.Logf("sigwinch...")
+\tt.Logf("sighup...")
 	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
 	waitSig(t, c1, syscall.SIGHUP)
 

コアとなるコードの解説

上記の差分は、signal_test.go内のTestSignal関数におけるt.Logf呼び出しの変更を示しています。

  1. 最初の変更ブロック:

    -\tt.Logf("sighup...")
    	// Send this process a SIGHUP
    +\tt.Logf("sighup...")
    

    ここでは、syscall.SIGHUPを送信する直前にt.Logf("sighup...")が移動されています。これは、ログメッセージがシグナル送信のイベントと時間的に密接に結びつくようにするための調整です。

  2. 2番目の変更ブロック:

    -\tt.Logf("sigwinch...")
    	// Send this process a SIGWINCH
    +\tt.Logf("sigwinch...")
    

    同様に、syscall.SIGWINCHを送信する直前にt.Logf("sigwinch...")が移動されています。

  3. 3番目の変更ブロック:

    	// Send two more SIGHUPs, to make sure that
    	// they get delivered on c1 and that not reading
    	// from c does not block everything.
    -\tt.Logf("sigwinch...")
    +\tt.Logf("sighup...")
     	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)
     	waitSig(t, c1, syscall.SIGHUP)
    

-\tt.Logf("sigwinch...") +\tt.Logf("sighup...") syscall.Kill(syscall.Getpid(), syscall.SIGHUP) waitSig(t, c1, syscall.SIGHUP) ``` この部分が最も重要な修正です。ここでは、コメントで示されているようにSIGHUPシグナルが送信されています。しかし、元のコードではt.Logf("sigwinch...")と誤ったメッセージが出力されていました。このコミットにより、t.Logf("sighup...")に修正され、ログが実際のシグナル送信と一致するようになりました。

これらの変更はすべて、テストのログ出力をより正確で分かりやすいものにすることを目的としており、os/signalパッケージの機能的な動作には影響を与えません。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • コミットの差分情報
  • Go言語のos/signalパッケージのソースコード
  • Go言語のtestingパッケージのソースコード
  • Go言語のsyscallパッケージのソースコード
  • 一般的なUnixシグナルに関する知識