Go进程在捕获SIGINT和SIGTERM时过早死亡
我有一个相当直接的信号处理和清理过程:Go进程在捕获SIGINT和SIGTERM时过早死亡,go,signals,Go,Signals,我有一个相当直接的信号处理和清理过程: func signalHandler(shutdown func() error) { // Make signal channel and register notifiers for Interupt and Terminate sigchan := make(chan os.Signal, 1) signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM) // Bl
func signalHandler(shutdown func() error) {
// Make signal channel and register notifiers for Interupt and Terminate
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM)
// Block until we receive a signal on the channel
<-sigchan
// Shutdown now that we've received the signal
if err := shutdown(); err != nil {
msg := fmt.Sprintf("shutdown error: %s", err.Error())
log.Fatal(msg)
}
log.Println("shutdown procedure complete")
// Make a clean exit
os.Exit(0)
}
func信号处理程序(shutdown func()错误){
//建立信号通道并注册中断和终止通知程序
sigchan:=make(通道操作信号,1)
signal.Notify(sigchan、syscall.SIGINT、syscall.SIGTERM)
//阻塞,直到我们收到频道上的信号
问题是对Run()
的调用是main()
中最后一个真正的操作。只要Run()
返回,main()
返回,当main()
返回时,程序退出。我通常将信号处理放在main()
本身,而不是任何goroutine中,以确保main()
在我处理完信号关闭后程序之前不会返回
(从评论中可以看出,现在已经排序,重新发布作为答案。)问题是对Run()
的调用是main()
中的最后一个实际操作。只要Run()
返回,main()
返回,并且当main()
返回时,程序退出。我通常将信号处理放在main()中
本身,而不是在任何goroutine中,以确保main()
在处理完信号关闭后程序之前不会返回
(从评论中,现在已排序,重新发布作为答案。)是s.done
缓冲通道吗?shutdown
不调用*Server.shutdown()
,它是*Server.shutdown()
-我将它直接传递到*Server.Run()中的信号处理器中
方法。我尝试了缓冲和非缓冲-效果相同。没有同步来等待运行完成,因此不能保证永远打印,但“此处全部完成”应该写入日志。日志输出是标准的非缓冲标准吗?是main()
调用server.Run()
并检查是否有错误,然后记录它——这是它最后做的事情。s.done
是缓冲通道吗?shutdown
不调用*Server.shutdown()
,它是*Server.shutdown()
-我将它直接传递到*服务器中的信号处理器中。Run()
方法。我尝试了缓冲和非缓冲-效果相同。没有同步来等待运行完成,因此不能保证永远打印,但“此处全部完成”应该写入日志。日志输出是标准的非缓冲标准吗?是main()
调用server.Run()
并检查是否有错误,然后将其记录下来——这是它最后做的事情。
func (s *Server) Run() error {
go signalHandler(s.Shutdown)
...
<-s.done // block until done
log.Println("done running!")
return nil
}
func (s *Server) Shutdown() error {
s.done <- true
log.Println("all done here!")
return nil
}