Golang Go语言程序无故退出,panic也捕获不到,求解决方案

发布于 1周前 作者 nodeper 来自 Go语言

程序里面用了若干 go 子线程(盲猜问题在子线程但是无法定位),有些错误会直接 os.exit ,每个函数方法都写了 panic 捕获写日志,程序退出时不会返回 panic 。

大神们有什么好的办法定位错误处吗?

生产环境问题出了几个月还是找不到问题,有时运行半天,有时运行几天,退出的时候 cpu 和内存都没有大量占用


Golang Go语言程序无故退出,panic也捕获不到,求解决方案
32 回复

b os.exit

更多关于Golang Go语言程序无故退出,panic也捕获不到,求解决方案的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


试试 sentry ?

找找有没有不安全指针

attach processes 或者直接远程上去 debug ?

我最近也遇到了类似的 Bug ,服务器崩溃了,但是 Sentry 无法收集到崩溃,但是退出还是有日志的。

我遇到的情况是这样的:一个第三方库出了些问题,在 map 里面野指针了。而 Map 在 Go Runtime 里面的实现是 ASM 实现的,然后 Link 到 Runtime 里面。如果 ASM 内部发生了野指针相关的问题,直接会被系统走了 unix signal 退出,导致无法被 recover handle 。

我看日志说 os.Exit() 会把程序立即退出,这个真的是你需要的函数吗?

设置环境变量 GOTRACEBACK=crash 运行 Go 程序,core dump 后用 GDB 查,参见: https://pkg.go.dev/runtime

不是自己主动写的 os.exit 而是一些莫名的错误导致的

就是找起来很麻烦 代码行一多逻辑一复杂简直不可能

你是如何找到错误地方的?

1.lint 错误全部要修改过来
2.race 运行检测
3.付费请人

错误只会产生 err ,Exit 自己主动调用才会被执行

map 并发读写导致的程序崩溃。这种崩溃通过 panic 无法捕捉,检查下全局 map 是否有并发读写的情况吧。

看看日志库,有没有接管退出方法,导致退出前没有 flush 日志。

如果短时间可以浮现,服务器上 nohup strace 启动服务看退出前的行为。

先跑一遍 golangci-lint 吧。

这个会有堆栈信息的

  1. strace
    可以有这个 api 的调用关系

    2. gdb
    有堆栈

log 文件呀,我 go 的 binary 的启动是套了一层 supervisor 的,在 supervisor 对应的 err 里面是有崩溃 stack trace 的

在 Goroutines 里面写 defer func(){}

像楼上说的,多打日志。我之前也是有这种类似的情况,多打日志就好了,极限一点每个模块都用不同的日志文件记录,方便定位

我只是在每个子线程里面的 defer 捕获 panic ,但是出错的地方根本没有返回 panic ,感觉是直接 os
.exit 了

打了日志啊,根本没有信息

supervisor 是啥 属于 go 的范围吗?还是 linux 层面的?

跑了没问题

貌似直接崩溃有好些可能性,比如指针错误,并发写入公共变量,还有第三方库可能是 os.exit

本质上就是 stderr 啊…

什么神仙第三方库会 os.Exit() ?

提示一点……panic 日志是不会打在你指定的文件里的,总是输出到 stderr

所以如果你没对 stderr 进行重定向的话,应该是看不到日志的。

目前看起来是猜测已经够多了只差验证了,我提供一个验证的思路:利用 BPF 技术追踪下 os.Exit 和 panic 调用,能够定位到底是因为哪一种方式导致程序退出的。

panic 可以捕获啊,捕获后想怎么样都可以

你调用第三方库,它自己开了个协程的话,你是没法捕获的…

panic 在外面捕获不到的,一般都是在 go func 协程里崩的,得在协程里 recover 才行

针对您提到的Golang程序无故退出且panic未捕获的问题,这里有几个可能的解决方向:

  1. 检查系统资源:程序可能因为系统资源耗尽(如内存、文件描述符等)而被迫退出。可以使用工具如tophtopgo tool pprof来监控和分析资源使用情况。

  2. 信号处理:程序可能接收到某些系统信号(如SIGKILL、SIGTERM)导致立即退出。可以通过自定义信号处理来捕获这些信号,进行资源清理或记录日志。

  3. CGo和底层库:如果程序中使用了CGo调用C语言代码或外部库,这些代码可能触发未捕获的异常或错误,导致进程退出。检查CGo调用部分及其依赖库的稳定性和错误处理。

  4. 静态分析工具:使用如golintgo vet等静态分析工具检查代码中的潜在问题,特别是未处理的错误返回值。

  5. 核心转储(Core Dump):如果程序异常退出,可以尝试生成核心转储文件,通过gdb等工具分析转储文件,查找崩溃原因。

  6. 日志和监控:增强日志记录,特别是在程序的关键路径和异常处理代码中,确保能捕捉到尽可能多的运行时信息。同时,考虑实施更全面的监控策略。

建议从上述方面逐一排查,结合具体的程序结构和运行环境,找出导致程序无故退出的根本原因。

回到顶部