英文:
Go process prematurely dies when capturing SIGINT and SIGTERM
问题
我有一个相当简单的信号处理和清理过程:
func signalHandler(shutdown func() error) {
// 创建信号通道并注册中断和终止的通知器
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, syscall.SIGINT, syscall.SIGTERM)
// 阻塞,直到我们在通道上接收到一个信号
<-sigchan
// 收到信号后立即关闭
if err := shutdown(); err != nil {
msg := fmt.Sprintf("shutdown error: %s", err.Error())
log.Fatal(msg)
}
log.Println("关闭程序完成")
// 干净退出
os.Exit(0)
}
这个处理程序从服务器中运行一个Go协程:
func (s *Server) Run() error {
go signalHandler(s.Shutdown)
...
<-s.done // 阻塞直到完成
log.Println("运行完成!")
return nil
}
func (s *Server) Shutdown() error {
s.done <- true
log.Println("全部完成!")
return nil
}
问题是在打印"log.Println("全部完成!")"之前,进程就退出了,有时会打印"运行完成!",有时不会。似乎在我使用的某个库中有一个os.Exit()
调用。我确实需要清理连接和删除临时文件等,但它们没有被正确清理。
有人知道我如何诊断进程在哪里退出吗?
更新:我添加了"log.Println("关闭程序完成")"语句,但我也没有看到它。似乎在这个函数结束之前,进程就终止了。
英文:
I have a fairly straight forward signal handling and cleanup process:
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)
}
This hander is running a go routine from the server:
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
}
The problem is that the process exits before the "all done here!" can be printed to the log, and sometimes "done running" prints and other times it doesn't. It seems like there is an os.Exit()
call somewhere else (possibly in one of the libraries I'm using?). I do need to clean up connections and delete temporary files etc, and they're not getting cleaned up properly.
Does anyone know how I diagnose where the process is exiting?
Update: I'm also not seeing "shutdown procedure complete" with the addition of that log statement. It appears that the process is terminating before this function is over.
答案1
得分: 2
问题在于对Run()
的调用是main()
中的最后一个真正的操作。一旦Run()
返回,main()
也会返回,而当main()
返回时,程序就会退出。通常我会将信号处理放在main()
本身中,而不是在任何goroutine中,以确保在处理完信号后的关闭过程之前,main()
不会返回。
(从评论中重新发布为答案,现在已经解决。)
英文:
The issue is that the call to Run()
is the last real op in main()
. As soon as Run()
returns, main()
returns, and when main()
returns, the program exits. I generally put signal handling in main()
itself, rather than in any goroutine, to ensure that main()
does not return before I'm done handling post-signal shutdown procedures.
(From the comments, reposting as an answer now that it's sorted.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论