程序里面用了若干 go 子线程(盲猜问题在子线程但是无法定位),有些错误会直接 os.exit ,每个函数方法都写了 panic 捕获写日志,程序退出时不会返回 panic 。
大神们有什么好的办法定位错误处吗?
生产环境问题出了几个月还是找不到问题,有时运行半天,有时运行几天,退出的时候 cpu 和内存都没有大量占用
![]() | 1 nuk 2022-04-11 00:25:38 +08:00 b os.exit |
![]() | 2 ETiV 2022-04-11 00:40:38 +08:00 via iPhone 试试 sentry ? |
![]() | 3 foam 2022-04-11 00:41:15 +08:00 via Android 找找有没有不安全指针 |
4 kwanzaa 2022-04-11 00:44:20 +08:00 attach processes 或者直接远程上去 debug ? |
![]() | 5 txx 2022-04-11 01:13:05 +08:00 ![]() 我最近也遇到了类似的 Bug ,服务器崩溃了,但是 Sentry 无法收集到崩溃,但是退出还是有日志的。 我遇到的情况是这样的:一个第三方库出了些问题,在 map 里面野指针了。而 Map 在 Go Runtime 里面的实现是 ASM 实现的,然后 Link 到 Runtime 里面。如果 ASM 内部发生了野指针相关的问题,直接会被系统走了 unix signal 退出,导致无法被 recover handle 。 |
![]() | 6 CEBBCAT 2022-04-11 01:36:11 +08:00 我看日志说 os.Exit() 会把程序立即退出,这个真的是你需要的函数吗? |
![]() | 7 kinghui 2022-04-11 07:14:07 +08:00 设置环境变量 GOTRACEBACK=crash 运行 Go 程序,core dump 后用 GDB 查,参见: https://pkg.go.dev/runtime |
![]() | 11 dbskcnc 2022-04-11 09:21:49 +08:00 1.lint 错误全部要修改过来 2.race 运行检测 3.付费请人 |
![]() | 13 xmge 2022-04-11 10:00:23 +08:00 map 并发读写导致的程序崩溃。这种崩溃通过 panic 无法捕捉,检查下全局 map 是否有并发读写的情况吧。 |
14 luwill 2022-04-11 10:56:39 +08:00 看看日志库,有没有接管退出方法,导致退出前没有 flush 日志。 如果短时间可以浮现,服务器上 nohup strace 启动服务看退出前的行为。 |
15 joesonw 2022-04-11 11:09:55 +08:00 via iPhone 先跑一遍 golangci-lint 吧。 |
17 xsen 2022-04-11 12:39:50 +08:00 1. strace 可以有这个 api 的调用关系 2. gdb 有堆栈 |
![]() | 18 txx 2022-04-11 15:09:26 +08:00 @herozzm log 文件呀,我 go 的 binary 的启动是套了一层 supervisor 的,在 supervisor 对应的 err 里面是有崩溃 stack trace 的 |
19 MeetTheFuture 2022-04-11 15:52:10 +08:00 在 Goroutines 里面写 defer func(){} |
![]() | 20 kirisamemarisas 2022-04-11 16:17:33 +08:00 像楼上说的,多打日志。我之前也是有这种类似的情况,多打日志就好了,极限一点每个模块都用不同的日志文件记录,方便定位 |
![]() | 21 herozzm OP @MeetTheFuture 我只是在每个子线程里面的 defer 捕获 panic ,但是出错的地方根本没有返回 panic ,感觉是直接 os .exit 了 @kirisamemarisas 打了日志啊,根本没有信息 |
![]() | 26 CEBBCAT 2022-04-11 20:46:22 +08:00 什么神仙第三方库会 os.Exit() ? |
27 tairan2006 2022-04-12 10:24:25 +08:00 提示一点……panic 日志是不会打在你指定的文件里的,总是输出到 stderr 所以如果你没对 stderr 进行重定向的话,应该是看不到日志的。 |
28 yeqown 2022-04-12 11:22:10 +08:00 目前看起来是猜测已经够多了只差验证了,我提供一个验证的思路:利用 BPF 技术追踪下 os.Exit 和 panic 调用,能够定位到底是因为哪一种方式导致程序退出的。 |
![]() | 29 herozzm OP @tairan2006 panic 可以捕获啊,捕获后想怎么样都可以 |
30 tairan2006 2022-04-12 13:16:46 +08:00 via Android @herozzm 你调用第三方库,它自己开了个协程的话,你是没法捕获的… |
31 smartshallot 2022-04-14 22:44:54 +08:00 @herozzm panic 在外面捕获不到的,一般都是在 go func 协程里崩的,得在协程里 recover 才行 |