go 程序无故退出, panic 也捕获不到,求解决方案 - V2EX
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 3496 次点击
    这是一个创建于 1279 天前的主题,其中的信息可能已经有所发展或是发生改变。

    程序里面用了若干 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() 会把程序立即退出,这个真的是你需要的函数吗?
    inghui
        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     Solana     5584 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 07:52 PVG 15:52 LAX 00:52 JFK 03:52
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86