Golang和SIGABRT

来源:互联网 发布:卓越物业软件 编辑:程序博客网 时间:2024/05/16 17:18

golang函数signal.Notify允许程序对诸如SIGINT, SIGKILL这样的进程信号进行响应, 尤指通过注册事件handler。 不过golang用户应该避免捕获SIGABRT, 在本篇博客中解释了为什么。

接下来的这一个程序解释了为什么捕获SIGABRT是一个坏主意:

package mainimport (    "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.gopid: 14755

程序打印了它的进程ID并且等待信号, 或通过kill命令, 若程序运行于前台也可通过Ctrl-C:

$ go run main.gopid: 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.gopid: 14765

在另一个会话中发送SIGABRT:

$ kill -SIGABRT 14765

原文:
https://akutz.wordpress.com/2017/10/02/golang-and-sigabrt/

原创粉丝点击