以下の内容はhttps://devlights.hatenablog.com/entry/2025/04/28/073000より取得しました。


Goメモ-570 (signal使ったらsignal.Stop()をちゃんと呼ぶ)

関連記事

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。よく忘れるのでここにメモメモ。。。

シグナルを扱う場合、signal.Notifysignal.NotifyContext を呼んだ後に、お作法として signal.Stopを呼ぶべきなのですが、ネット上のサンプルとか自分では結構忘れていることが多いので、ここにメモしておくことにしました。

signal.Stopを呼ぶと、シグナルのハンドリングが停止されますので、当然その後のシグナルは受信しないようになります。

使い捨てのプログラムなら呼ばなくても問題ないですが、長時間処理するプロセスや何らかのフレームワークや基盤の上で動くプロセスの場合、シグナルはセンシティブに扱う必要があります。

サンプル

stop.go

package signals

import (
    "log"
    "os"
    "os/signal"
    "syscall"
    "time"
)

// Stop は、signal.Stop()のサンプルです.
//
// signal.Notify()などでハンドル処理を追加した場合
// ファイルの場合と同様に defer で signal.Stop() を呼ぶべき。
//
// > Stop causes package signal to stop relaying incoming signals to c.
// It undoes the effect of all prior calls to Notify using c. When Stop returns, it is guaranteed that c will receive no more signals.
//
// > Stopは、パッケージ・シグナルがcへの受信シグナルのリレーを停止させる。
// ストップが戻れば、cはそれ以上シグナルを受け取らないことが保証される。
//
// # REFERENCES
//   - https://pkg.go.dev/os/signal@go1.24.2#Stop
func Stop() error {
    var (
        l    = log.New(os.Stderr, "", log.Lmicroseconds)
        pid  = os.Getpid()
        sigs = make(chan os.Signal, 1)

        sendSig = func() {
            l.Println(">> SIGUSR1")
            _ = syscall.Kill(pid, syscall.SIGUSR1)
        }
        stopSig = func() {
            l.Println(">> signal.Stop")
            signal.Stop(sigs)
        }
    )
    defer close(sigs)

    signal.Notify(sigs, syscall.SIGUSR1, syscall.SIGUSR2)
    go func() {
        l.Printf("Signal recv: %v\n", <-sigs)
    }()

    l.Println("<START>")
    {
        sendSig()
        stopSig()
        sendSig()
    }
    time.Sleep(1 * time.Second)
    l.Println("< END >")

    return nil
}

実行結果

       $ task
        task: [build] go build -o "/workspaces/try-golang/try-golang" .
        task: [run] ./try-golang -onetime

        ENTER EXAMPLE NAME: signal_stop

        [Name] "signal_stop"
        06:03:32.489167 <START>
        06:03:32.489314 >> SIGUSR1
        06:03:32.489326 >> signal.Stop
        06:03:32.489444 >> SIGUSR1
        06:03:32.489442 Signal recv: user defined signal 1
        06:03:33.489539 < END >


        [Elapsed] 1.000858245s

signal.Stopを呼んだ後のシグナル(2発目)は受信出来ていないことが確認できますね。

参考情報

signal package - os/signal - Go Packages

Goのおすすめ書籍


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。




以上の内容はhttps://devlights.hatenablog.com/entry/2025/04/28/073000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14