博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
调试Go语言的核心转储(Core Dumps)
阅读量:6816 次
发布时间:2019-06-26

本文共 2868 字,大约阅读时间需要 9 分钟。

转帖/转载请注明出处

发表于2017/05/22 作者JBD是Go语言开发小组成员

检查程序的执行路径和当前状态是非常有用的调试手段。核心文件(core file)包含了一个运行进程的内存转储和状态。它主要是用来作为事后调试程序用的。它也可以被用来查看一个运行中的程序的状态。这两个使用场景使调试文件转储成为一个非常好的诊断手段。我们可以用这个方法来做事后诊断和分析线上的服务(production services)。

在这篇文章中,我们将用一个简单的hello world网站服务作为例子。在现实中,我们的程序很容易就会变得很复杂。分析核心转储给我们提供了一个机会去重构程序的状态并且查看只有在某些条件/环境下才能重现的案例。

作者注: 这个调试流程只在Linux上可行。我不是很确定它是否在其它Unixs系统上工作。macOS对此还不支持。Windows现在也不支持。

在我们开始前,需要确保核心转储的ulimit设置在合适的范围。它的缺省值是0,意味着最大的核心文件大小是0。我通常在我的开发机器上将它设置成unlimited。使用以下命令:

$ ulimit -c unlimited

接下来,你需要在你的机器上安装。

下面我们使用的main.go文件。它注册了一个简单的请求处理函数(handler)然后启动了HTTP服务。

$ cat main.gopackage mainimport (    "fmt"    "log"    "net/http")func main() {    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {        fmt.Fprint(w, "hello world\n")    })    log.Fatal(http.ListenAndServe("localhost:7777", nil))}

让我们编译并生产二进制文件。

$ go build .

现在让我们假设,这个服务器出了些问题,但是我们并不是很确定问题的根源。你可能已经在程序里加了很多辅助信息,但还是无法从这些调试信息中找出线索。通常在这种情况下,当前进程的快照会非常有用。我们可以用这个快照深入查看程序的当前状态。

有几个方式来获取核心文件。你可能已经熟悉了奔溃转储(crash dumps)。它们是在一个程序奔溃的时候写入磁盘的核心转储。Go语言在缺省设置下不会生产奔溃转储。但是当你把GOTRACEBACK环境变量设置成“crash”,你就可以用Ctrl+backslash才触发奔溃转储。如下图所示:

$ GOTRACEBACK=crash ./hello(Ctrl+\)

上面的操作会使程序终止,将堆栈跟踪(stack trace)打印出来,并把核心转储文件写入磁盘。

另外个方法可以从一个运行的程序获得核心转储而不需要终止相应的进程。gcore可以生产核心文件而无需使运行中的程序退出。

$ ./hello &$ gcore 546 # 546 is the PID of hello.

根据上面的操作,我们获得了转储而没有终止对应的进程。下一步就是把核心文件加载进delve并开始分析。

$ dlv core ./hello core.546

差不多就这些。delve的常用操作都可以使用。你可以backtrace,list,查看变量等等。有些功能不可用因为我们使用的核心转储是一个快照而不是正在运行的进程。但是程序执行路径和状态全部可以访问。

(dlv) bt 0  0x0000000000457774 in runtime.raise    at /usr/lib/go/src/runtime/sys_linux_amd64.s:110 1  0x000000000043f7fb in runtime.dieFromSignal    at /usr/lib/go/src/runtime/signal_unix.go:323 2  0x000000000043f9a1 in runtime.crash    at /usr/lib/go/src/runtime/signal_unix.go:409 3  0x000000000043e982 in runtime.sighandler    at /usr/lib/go/src/runtime/signal_sighandler.go:129 4  0x000000000043f2d1 in runtime.sigtrampgo    at /usr/lib/go/src/runtime/signal_unix.go:257 5  0x00000000004579d3 in runtime.sigtramp    at /usr/lib/go/src/runtime/sys_linux_amd64.s:262 6  0x00007ff68afec330 in (nil)    at :0 7  0x000000000040f2d6 in runtime.notetsleep    at /usr/lib/go/src/runtime/lock_futex.go:209 8  0x0000000000435be5 in runtime.sysmon    at /usr/lib/go/src/runtime/proc.go:3866 9  0x000000000042ee2e in runtime.mstart1    at /usr/lib/go/src/runtime/proc.go:118210  0x000000000042ed04 in runtime.mstart    at /usr/lib/go/src/runtime/proc.go:1152(dlv) ls> runtime.raise() /usr/lib/go/src/runtime/sys_linux_amd64.s:110 (PC: 0x457774)   105:     SYSCALL   106:     MOVL    AX, DI  // arg 1 tid   107:     MOVL    sig+0(FP), SI   // arg 2   108:     MOVL    $200, AX    // syscall - tkill   109:     SYSCALL=> 110:     RET   111:   112: TEXT runtime·raiseproc(SB),NOSPLIT,$0   113:     MOVL    $39, AX // syscall - getpid   114:     SYSCALL   115:     MOVL    AX, DI  // arg 1 pid

 

你可能感兴趣的文章
traceroute
查看>>
精通汇编语言,有兴趣一起搞破解的请进!
查看>>
C#缺省参数可以让代码变得更加简洁明了与时俱进心里敞亮了很多了
查看>>
【自然框架】js版的QuickPager分页控件 V2.0
查看>>
poj-2049 Finding Nemo *
查看>>
模块化编程本质探讨
查看>>
利用博客与视频分享和交流知识和经验
查看>>
js操作dom对象
查看>>
Windows2003服务器安全配置:先关闭不需要的端口(转自)
查看>>
HDU1247 Hat’s Words 【trie树】
查看>>
iOS开发--动画篇之layout动画深入
查看>>
WorldWind源码剖析系列:视景体类Frustum
查看>>
(转)完整java开发中JDBC连接数据库代码和步骤
查看>>
Redis Lua脚本原理
查看>>
有时间测试dism
查看>>
/Users/alamps/AndroidStudioProjects/Demo10ScrollView
查看>>
【Swift】iOS UICollectionView 计算 Cell 大小的陷阱
查看>>
为什么我刚发表的文章变成了“待审核”,csdn有没有官方解释啊
查看>>
Android多线程源码详解一:handler、looper、message、messageQueue
查看>>
SaaS加速器II 能力中心:互利互补 共享商业红利
查看>>