22
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Goで作ったプログラムでシグナルを受け取る

Last updated at Posted at 2015-09-19

シグナルを受ける

Goで作ったプログラム実行中にシグナルを受け取れるか試してみる。
これができれば、リモートからの通信や、他のイベントを1つのselectで一気に待機できるかも。
signal.Notify()というメソッドが用意されているので、これで試してみる。

godocを見ると、1つめの引数のチャネルに、登録したいシグナルを指定していくみたい。

// Notify causes package signal to relay incoming signals to c.
// If no signals are provided, all incoming signals will be relayed to c.
// Otherwise, just the provided signals will.
//
// Package signal will not block sending to c: the caller must ensure
// that c has sufficient buffer space to keep up with the expected
// signal rate.  For a channel used for notification of just one signal value,
// a buffer of size 1 is sufficient.
//
// It is allowed to call Notify multiple times with the same channel:
// each call expands the set of signals sent to that channel.
// The only way to remove signals from the set is to call Stop.
//
// It is allowed to call Notify multiple times with different channels
// and the same signals: each channel receives copies of incoming
// signals independently.
func Notify(c chan<- os.Signal, sig ...os.Signal) {

しかし、シグナルはどうやって指定するのか、、、、1とか2とかで選ぶのかな?
SIGTERMでGoの中をgrepすると、それっぽいファイルを発見。

./syscall/zerrors_darwin_amd64.go

当方マカーなのでdarwinがついているけど、windowsもあるみたい。
中をのぞいてみると、それっぽい。

// Signals
const (
	SIGABRT   = Signal(0x6)
	SIGALRM   = Signal(0xe)
	SIGBUS    = Signal(0xa)
	SIGCHLD   = Signal(0x14)
	SIGCONT   = Signal(0x13)
	SIGEMT    = Signal(0x7)
	SIGFPE    = Signal(0x8)
	SIGHUP    = Signal(0x1)
	SIGILL    = Signal(0x4)
	SIGINFO   = Signal(0x1d)
	SIGINT    = Signal(0x2)
	SIGIO     = Signal(0x17)
	SIGIOT    = Signal(0x6)
	SIGKILL   = Signal(0x9)
	SIGPIPE   = Signal(0xd)
	SIGPROF   = Signal(0x1b)
	SIGQUIT   = Signal(0x3)
	SIGSEGV   = Signal(0xb)
	SIGSTOP   = Signal(0x11)
	SIGSYS    = Signal(0xc)
	SIGTERM   = Signal(0xf)
	SIGTRAP   = Signal(0x5)
	SIGTSTP   = Signal(0x12)
	SIGTTIN   = Signal(0x15)
	SIGTTOU   = Signal(0x16)
	SIGURG    = Signal(0x10)
	SIGUSR1   = Signal(0x1e)
	SIGUSR2   = Signal(0x1f)
	SIGVTALRM = Signal(0x1a)
	SIGWINCH  = Signal(0x1c)
	SIGXCPU   = Signal(0x18)
	SIGXFSZ   = Signal(0x19)
)

とりあえずこれでやってみる。

package main

import (
	"fmt"
	"os"
	"syscall"

	"os/signal"
)

func main() {
	signalCh := make(chan os.Signal)
	// SIGHUPとSIGTERMとSIGKILLに対応する
	signal.Notify(signalCh, syscall.SIGHUP, syscall.SIGTERM, syscall.SIGKILL)

	for {

		select {
		case ch := <-signalCh:
			catchSig(ch)
		}
	}
}

func catchSig(sig os.Signal) {
	switch sig {
	case syscall.SIGHUP:
		fmt.Println("SIGHUP Happend! ", sig)
	case syscall.SIGTERM:
		fmt.Println("SIGTERM Happend! ", sig)
	case syscall.SIGKILL:
		fmt.Println("SIGKILL Happend! ", sig)
	default:
		fmt.Println("Other singal Happend! ", sig)
	}
}

これで動かすと。。。

$./samples &
[2] 34210
$
$ kill 34210
SIGTERM Happend! terminated
$ kill -1 34210
SIGHUP Happend! hangup
$ kill -9 34212
[2]+ Killed: 9 ./samples

さすがにSIGKILLは受け取れなかったけど、狙い通り。
一応未登録のシグナルも、発行してみる。

$ ./samples &
[2] 34226
$ kill -30 34226

やはり何も起こらない。SIGINTも発行する。

$ kill -2 34226
[2]+ Exit 2 ./samples

プログラムは何も受け取らないが、標準動作で終了する。
予期しないシグナルを防ぐには、何もしないように防ぐための登録が必要かも。

Windowsだとどうなる?

Windows版にも、ztypes_windows.goがあって、そこに定義があった。

const (
	// More invented values for signals
	SIGHUP  = Signal(0x1)
	SIGINT  = Signal(0x2)
	SIGQUIT = Signal(0x3)
	SIGILL  = Signal(0x4)
	SIGTRAP = Signal(0x5)
	SIGABRT = Signal(0x6)
	SIGBUS  = Signal(0x7)
	SIGFPE  = Signal(0x8)
	SIGKILL = Signal(0x9)
	SIGSEGV = Signal(0xb)
	SIGPIPE = Signal(0xd)
	SIGALRM = Signal(0xe)
	SIGTERM = Signal(0xf)
)

ここにあるシグナルは、受け取れるってことなのかな?
今度試してみよう。

22
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?