kurumi-bioの雑記帳

プログラミング、パソコン、ペット、 犬、お出かけ

初心者のGo言語 -38- <Ignore,Ignored,Notify>

こんにちは、kurumi-bioです。
第1回目のsignalパッケージ(標準ライブラリー)の学習です。

環境

  • Windows
    OSバージョン:Windows11 Home 22H2
    Go言語のバージョン:go version go1.20.3 windows/amd64
  • Linux
    OSバージョン:openSUSE Leap 15.4
    Go言語のバージョン:go version go1.20.3 linux/amd64

Ignore関数

func Ignore(sig ...os.Signal)

関数の説明 Ignoreは、提供されたシグナルが無視されます。 プログラムがそれらを受信して​​も、何も起こりません。 Ignore は、提供されたシグナルに対する以前の Notify 呼び出しの効果を取り消します。信号が提供されない場合、すべての受信信号は無視されます。

Ignored関数

func Ignored(sig os.Signal) bool

関数の説明 Ignored は、sig が現在無視されているかどうかを報告します。

◆テストコード

package main

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

func main() {
    fmt.Printf("pid=[%d]\n", os.Getpid())
    signal.Ignore(syscall.SIGINT, syscall.SIGTERM)
    fmt.Println("Ignored Start")
    fmt.Printf("syscall.SIGKILL=[%v]\n", signal.Ignored(syscall.SIGKILL))
    fmt.Printf("syscall.SIGINT=[%v]\n", signal.Ignored(syscall.SIGINT))
    fmt.Printf("syscall.SIGTERM=[%v]\n", signal.Ignored(syscall.SIGTERM))
    time.Sleep(10 * time.Second)
    fmt.Println("end")
}

コードの説明 実行するとpidを表示し、signal.Ignore()関数を使ってsyscall.SIGINTとsyscall.SIGTERMのシグナルを10秒間無視します。
また、signal.Ignored()関数を使ってsyscall.SIGKILL、syscall.SIGINT、syscall.SIGTERMが無視されているか表示します。

◆実行結果(Windows)

◆実行結果(Linux)

実行結果の説明

  • Windows
    Ctrl+cを押すとプロセスが終了しました。
    Windowsは、signal.Ignored()関数が対応していないと思われます。

  • Linux
    Ctrl+cを押しても、kill <プロセスid>を実行してもプロセスが終了しませんでした。

Notify関数

func Notify(c chan<- os.Signal, sig ...os.Signal)

関数の説明 Notify により、パッケージ信号は受信信号を c に中継します。信号が提供されない場合、すべての受信信号は c に中継されます。それ以外の場合は、提供された信号のみが表示されます。

パッケージ信号は c への送信をブロックしません。呼び出し元は、期待される信号速度に対応するのに十分なバッファー領域が c にあることを確認する必要があります。 1 つの信号値のみの通知に使用されるチャネルの場合、サイズ 1 のバッファで十分です。

同じチャネルで Notify を複数回呼び出すことができます。呼び出しごとに、そのチャネルに送信される信号のセットが拡張されます。セットから信号を削除する唯一の方法は、Stop を呼び出すことです。

異なるチャネルと同じ信号を使用して Notify を複数回呼び出すことができます。各チャネルは着信信号のコピーを個別に受信します。

◆テストコード

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
)

func main() {
    signal.Ignore(syscall.SIGINT, syscall.SIGTERM)

    fmt.Printf("pid=[%d]\n", os.Getpid())
    for {
        c := make(chan os.Signal, 1)
        signal.Notify(c)
        s := <-c
        fmt.Printf("signal=[%s]\n", s)
    }
}

コードの説明 signal.Ignore()関数を使ってsyscall.SIGINTとsyscall.SIGTERMのシグナルを無視します。 無限ループで、signal.Notify()関数を使って受け取ったシグナルを表示します。

◆実行結果(Windows)

◆実行結果(Linux)

実行結果の説明

  • Windows
    Ctrl+cを押すと"interrup"のシグナルを受信しました。
    プロセスが停止しなかったのでタスクマネージャで強制終了しました。

  • Linux
    Ctrl+cを押すと"interrupt"のシグナルを受信
    Ctrl+zを押すと"stopped"のシグナルを受信
    kill <プロセスId>で、"terminated"のシグナルを受信
    Kill -9 <プロセスId>で強制終了しました。  

最後までご覧いただきありがとうございます