Go语言 signal.Notify 信号量的使用(优雅关闭进程资源)
Posted 张志翔ۤ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言 signal.Notify 信号量的使用(优雅关闭进程资源)相关的知识,希望对你有一定的参考价值。
go中的信号量:
信号 | 值 | 动作 | 说明 |
---|---|---|---|
SIGHUP | 1 | Term | 终端控制进程结束(终端连接断开) |
SIGINT | 2 | Term | 用户发送INTR字符(Ctrl+C)触发 |
SIGQUIT | 3 | Core | 用户发送QUIT字符(Ctrl+/)触发 |
SIGILL | 4 | Core | 非法指令(程序错误、试图执行数据段、栈溢出等) |
SIGABRT | 6 | Core | 调用abort函数触发 |
SIGFPE | 8 | Core | 算术运行错误(浮点运算错误、除数为零等) |
SIGKILL | 9 | Term | 无条件结束程序(不能被捕获、阻塞或忽略) |
SIGSEGV | 11 | Core | 无效内存引用(试图访问不属于自己的内存空间、对只读内存空间进行写操作) |
SIGPIPE | 13 | Term | 消息管道损坏(FIFO/Socket通信时,管道未打开而进行写操作) |
SIGALRM | 14 | Term | 时钟定时信号 |
SIGTERM | 15 | Term | 结束程序(可以被捕获、阻塞或忽略) |
SIGUSR1 | 30,10,16 | Term | 用户保留 |
SIGUSR2 | 31,12,17 | Term | 用户保留 |
SIGCHLD | 20,17,18 | Ign | 子进程结束(由父进程接收) |
SIGCONT | 19,18,25 | Cont | 继续执行已经停止的进程(不能被阻塞) |
SIGSTOP | 17,19,23 | Stop | 停止进程(不能被捕获、阻塞或忽略) SIGTSTP 18,20,24 Stop 停止进程(可以被捕获、阻塞或忽略) SIGTTIN 21,21,26 Stop 后台程序从终端中读取数据时触发 SIGTTOU 22,22,27 Stop 后台程序向终端中写数据时触发 |
有些信号名对应着3个信号值,这是因为这些信号值与平台相关,SIGKILL和SIGSTOP这两个信号既不能被应用程序捕获,也不能被操作系统阻塞或忽略。
优雅地退出程序
在长时间的程序运行过程中,可能有大量的系统资源被申请,无论在以何种方式退出前,他们应该及时将这些资源释放并将状态输出到日志中方便调试和排错。
signal.Notify方法监听和捕获信号量
func Notify(c chan<- os.Signal, sig …os.Signal)
首先定义一个 c 传递信号量,然后说明那些信号量是需要被捕获的,信号量没有捕获到就会阻塞在这里(不填的话就默认捕获任何信号量):
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
监听信号量输出(只要上述三种信号量有输出,就会停止阻塞,执行代码):
func terminal() {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
select {
case <-c:
log.Infof("stop signal caught, pid[%d] stopping...", os.Getpid())
}
http.Shutdown()
rpc.Shutdown()
log.Info("transfer has stopped successfully !!!")
}
还有另一种方式可以根据不同信号量捕获做不同的逻辑处理,代码如下:
func terminal() {
sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
select {
switch sig {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
log.Panic("SIGQUIT")
case syscall.SIGHUP:
log.Panic("SIGHUP")
case syscall.SIGHUP:
log.Panic("SIGINT")
}
http.Shutdown()
rpc.Shutdown()
log.Info("transfer has stopped successfully !!!")
}
terminal 方法放到 main.go 的最后一行执行,一直阻塞直到捕获到对应信号量做终止进程的相关后续处理。
到此 Go语言 signal.Notify 优雅关闭进程资源介绍完成。
以上是关于Go语言 signal.Notify 信号量的使用(优雅关闭进程资源)的主要内容,如果未能解决你的问题,请参考以下文章