V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
herozzm

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

  •  
  •   herozzm · Apr 11, 2022 via Android · 3799 views
    This topic created in 1489 days ago, the information mentioned may be changed or developed.

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

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

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

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

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

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

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

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

    所以如果你没对 stderr 进行重定向的话,应该是看不到日志的。
    yeqown
        28
    yeqown  
       Apr 12, 2022
    目前看起来是猜测已经够多了只差验证了,我提供一个验证的思路:利用 BPF 技术追踪下 os.Exit 和 panic 调用,能够定位到底是因为哪一种方式导致程序退出的。
    herozzm
        29
    herozzm  
    OP
       Apr 12, 2022
    @tairan2006 panic 可以捕获啊,捕获后想怎么样都可以
    tairan2006
        30
    tairan2006  
       Apr 12, 2022 via Android
    @herozzm 你调用第三方库,它自己开了个协程的话,你是没法捕获的…
    smartshallot
        31
    smartshallot  
       Apr 14, 2022
    @herozzm panic 在外面捕获不到的,一般都是在 go func 协程里崩的,得在协程里 recover 才行
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   959 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 61ms · UTC 19:53 · PVG 03:53 · LAX 12:53 · JFK 15:53
    ♥ Do have faith in what you're doing.