我有一个相当直接的信号处理和清理过程:
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 (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
}
问题是该过程在“所有完成此处!”之前退出。可以打印到日志,有时“完成运行”打印,有时则不打印。好像在其他地方有一个os.Exit()
调用(可能在我正在使用的一个库中?)。我确实需要清理连接并删除临时文件等,并且它们没有得到正确的清理。
有谁知道我如何诊断流程退出的位置?
更新:我还没有看到添加该日志语句的“关闭过程完成”。看来该过程在此功能结束之前终止。
答案 0 :(得分:2)
问题是对Run()
的调用是main()
中的最后一个真实操作。只要Run()
返回,main()
返回,当main()
返回时,程序退出。我通常将信号处理放在main()
本身而不是任何goroutine中,以确保在我处理信号后关闭程序之前main()
没有返回。
(根据评论,现在将其作为答案重新排序。)