V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
herozzm
V2EX  ›  Go 编程语言

go 程序无故退出, panic 也捕获不到,求解决方案

  •  
  •   herozzm · 2022-04-11 00:11:38 +08:00 via Android · 3091 次点击
    这是一个创建于 956 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    31 条回复    2022-04-14 22:44:54 +08:00
    nuk
        1
    nuk  
       2022-04-11 00:25:38 +08:00
    b os.exit
    ETiV
        2
    ETiV  
       2022-04-11 00:40:38 +08:00 via iPhone
    试试 sentry ?
    foam
        3
    foam  
       2022-04-11 00:41:15 +08:00 via Android
    找找有没有不安全指针
    kwanzaa
        4
    kwanzaa  
       2022-04-11 00:44:20 +08:00
    attach processes 或者直接远程上去 debug ?
    txx
        5
    txx  
       2022-04-11 01:13:05 +08:00   ❤️ 2
    我最近也遇到了类似的 Bug ,服务器崩溃了,但是 Sentry 无法收集到崩溃,但是退出还是有日志的。

    我遇到的情况是这样的:一个第三方库出了些问题,在 map 里面野指针了。而 Map 在 Go Runtime 里面的实现是 ASM 实现的,然后 Link 到 Runtime 里面。如果 ASM 内部发生了野指针相关的问题,直接会被系统走了 unix signal 退出,导致无法被 recover handle 。
    CEBBCAT
        6
    CEBBCAT  
       2022-04-11 01:36:11 +08:00
    我看日志说 os.Exit() 会把程序立即退出,这个真的是你需要的函数吗?
    kinghui
        7
    kinghui  
       2022-04-11 07:14:07 +08:00
    设置环境变量 GOTRACEBACK=crash 运行 Go 程序,core dump 后用 GDB 查,参见: https://pkg.go.dev/runtime
    herozzm
        8
    herozzm  
    OP
       2022-04-11 07:26:08 +08:00 via Android
    @CEBBCAT 不是自己主动写的 os.exit 而是一些莫名的错误导致的
    herozzm
        9
    herozzm  
    OP
       2022-04-11 07:27:16 +08:00 via Android
    @foam 就是找起来很麻烦 代码行一多逻辑一复杂简直不可能
    herozzm
        10
    herozzm  
    OP
       2022-04-11 07:28:38 +08:00 via Android
    @txx 你是如何找到错误地方的?
    dbskcnc
        11
    dbskcnc  
       2022-04-11 09:21:49 +08:00
    1.lint 错误全部要修改过来
    2.race 运行检测
    3.付费请人
    CEBBCAT
        12
    CEBBCAT  
       2022-04-11 09:25:32 +08:00 via iPhone
    @herozzm 错误只会产生 err ,Exit 自己主动调用才会被执行
    xmge
        13
    xmge  
       2022-04-11 10:00:23 +08:00
    map 并发读写导致的程序崩溃。这种崩溃通过 panic 无法捕捉,检查下全局 map 是否有并发读写的情况吧。
    luwill
        14
    luwill  
       2022-04-11 10:56:39 +08:00
    看看日志库,有没有接管退出方法,导致退出前没有 flush 日志。

    如果短时间可以浮现,服务器上 nohup strace 启动服务看退出前的行为。
    joesonw
        15
    joesonw  
       2022-04-11 11:09:55 +08:00 via iPhone
    先跑一遍 golangci-lint 吧。
    lasuar
        16
    lasuar  
       2022-04-11 11:32:09 +08:00
    @xmge 这个会有堆栈信息的
    xsen
        17
    xsen  
       2022-04-11 12:39:50 +08:00
    1. strace
    可以有这个 api 的调用关系

    2. gdb
    有堆栈
    txx
        18
    txx  
       2022-04-11 15:09:26 +08:00
    @herozzm log 文件呀,我 go 的 binary 的启动是套了一层 supervisor 的,在 supervisor 对应的 err 里面是有崩溃 stack trace 的
    MeetTheFuture
        19
    MeetTheFuture  
       2022-04-11 15:52:10 +08:00
    在 Goroutines 里面写 defer func(){}
    kirisamemarisas
        20
    kirisamemarisas  
       2022-04-11 16:17:33 +08:00
    像楼上说的,多打日志。我之前也是有这种类似的情况,多打日志就好了,极限一点每个模块都用不同的日志文件记录,方便定位
    herozzm
        21
    herozzm  
    OP
       2022-04-11 16:26:18 +08:00
    @MeetTheFuture 我只是在每个子线程里面的 defer 捕获 panic ,但是出错的地方根本没有返回 panic ,感觉是直接 os
    .exit 了

    @kirisamemarisas 打了日志啊,根本没有信息
    herozzm
        22
    herozzm  
    OP
       2022-04-11 16:26:52 +08:00
    @txx supervisor 是啥 属于 go 的范围吗?还是 linux 层面的?
    herozzm
        23
    herozzm  
    OP
       2022-04-11 16:27:17 +08:00
    @joesonw 跑了没问题
    herozzm
        24
    herozzm  
    OP
       2022-04-11 16:28:15 +08:00
    @xmge 貌似直接崩溃有好些可能性,比如指针错误,并发写入公共变量,还有第三方库可能是 os.exit
    txx
        25
    txx  
       2022-04-11 16:53:02 +08:00
    @herozzm 本质上就是 stderr 啊...
    CEBBCAT
        26
    CEBBCAT  
       2022-04-11 20:46:22 +08:00
    什么神仙第三方库会 os.Exit() ?
    tairan2006
        27
    tairan2006  
       2022-04-12 10:24:25 +08:00
    提示一点……panic 日志是不会打在你指定的文件里的,总是输出到 stderr

    所以如果你没对 stderr 进行重定向的话,应该是看不到日志的。
    yeqown
        28
    yeqown  
       2022-04-12 11:22:10 +08:00
    目前看起来是猜测已经够多了只差验证了,我提供一个验证的思路:利用 BPF 技术追踪下 os.Exit 和 panic 调用,能够定位到底是因为哪一种方式导致程序退出的。
    herozzm
        29
    herozzm  
    OP
       2022-04-12 12:38:11 +08:00
    @tairan2006 panic 可以捕获啊,捕获后想怎么样都可以
    tairan2006
        30
    tairan2006  
       2022-04-12 13:16:46 +08:00 via Android
    @herozzm 你调用第三方库,它自己开了个协程的话,你是没法捕获的…
    smartshallot
        31
    smartshallot  
       2022-04-14 22:44:54 +08:00
    @herozzm panic 在外面捕获不到的,一般都是在 go func 协程里崩的,得在协程里 recover 才行
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3360 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 04:57 · PVG 12:57 · LAX 20:57 · JFK 23:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.