golang函数signal.Notify允许程序对诸如SIGINT, SIGKILL这样的进程信号进行响应, 尤指通过注册事件handler。 不过golang用户应该避免捕获SIGABRT, 在本篇博客中解释了为什么。
接下来的这一个程序解释了为什么捕获SIGABRT是一个坏主意:
package main
import (
"fmt"
"os"
"os/signal"
"strings"
"syscall"
)
func main() {
// Print the process ID to make it easier to send this program a signal.
fmt.Printf("pid: %d\n", os.Getpid())
// If this program's first argument is "trap" then trap SIGABRT.
if len(os.Args) > 1 && strings.EqualFold(os.Args[1], "trap") {
n := make(chan os.Signal, 1)
signal.Notify(n, syscall.SIGABRT)
go func() {
for sig := range n {
fmt.Println(sig)
os.Exit(1)
}
}()
}
// Use a channel to block the program by waiting indefinitely
// until something reads the channel (which will never happen).
c := make(chan struct{})
<-c
}
上面程序的最后两行保证了进程永远不退出, 除非向它发送了一个信号让它退出, 例如:
$ go run main.go
pid: 14755
程序打印了它的进程ID并且等待信号, 或通过kill命令, 若程序运行于前台也可通过Ctrl-C:
$ go run main.go
pid: 14755
^Csignal: interrupt
通过信号让进程结束并非新鲜事。 不过,
Golang程序将SIGABRT解释为一个特殊事件, 并且引发一次core dump 包含所有的协程, 如果他们死锁的话。
Golang programs interpret the SIGABRT signal as a special event that forces a core dump, including all goroutines and if they’re deadlocked.
将以上程序再度运行, 不过本次不是用Ctrl-C或者发送SIGINT, 而是在另外一个session中发送一个SIGABRT信号。
$ go run main.go
pid: 14765
在另一个会话中发送SIGABRT:
$ kill -SIGABRT 14765
原文:
https://akutz.wordpress.com/2017/10/02/golang-and-sigabrt/