Golang和SIGABRT

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/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值