Golang控制panic stack trace的深度

緣起

在進(jìn)行Golang開(kāi)發(fā)過(guò)程中铺峭,出現(xiàn)一個(gè)問(wèn)題:運(yùn)行g(shù)olang寫(xiě)的程序時(shí)出現(xiàn)異常纱兑,信息如下:

bjlvxin@bjlvxin-Vostro-270:/sourcecode/go/work/src/github.com/tiger/mygate/cmd$ go version
go version go1.10.3 linux/amd64
bjlvxin@bjlvxin-Vostro-270:/sourcecode/go/work/src/github.com/tiger/mygate/cmd$ ./build.sh 
bjlvxin@bjlvxin-Vostro-270:/sourcecode/go/work/src/github.com/tiger/mygate/cmd$ ./mygate 
panic: http: multiple registrations for /debug/requests

goroutine 1 [running]:
net/http.(*ServeMux).Handle(0x149f340, 0xdbfe9b, 0xf, 0xe524a0, 0xdf2318)
    /software/servers/go1.10.3/src/net/http/server.go:2353 +0x239
net/http.(*ServeMux).HandleFunc(0x149f340, 0xdbfe9b, 0xf, 0xdf2318)
    /software/servers/go1.10.3/src/net/http/server.go:2368 +0x55
net/http.HandleFunc(0xdbfe9b, 0xf, 0xdf2318)
    /software/servers/go1.10.3/src/net/http/server.go:2380 +0x4b
golang.org/x/net/trace.init.0()
    /sourcecode/go/work/src/golang.org/x/net/trace/trace.go:115 +0x42

看到這樣的錯(cuò)誤堆棧因俐,我也是醉了榴嗅,根本沒(méi)有任何實(shí)際的價(jià)值妄呕。從錯(cuò)誤堆棧中看不出到底是引用的哪個(gè)包導(dǎo)致重復(fù)注冊(cè) /debug/requests。

解決方案

有兩種方案可以解決該問(wèn)題嗽测,從而展現(xiàn)出更多的錯(cuò)誤堆棧信息:

方案一:降低Golang版本

先前我使用的golang的版本是:1.10.3绪励,將golang的版本換成1.9.0之后,重新編譯運(yùn)行唠粥,可以看到打印出了更多的信息:

bjlvxin@bjlvxin-Vostro-270:/sourcecode/go/work/src/github.com/tiger/mygate/cmd$ go version
go version go1.9.2 linux/amd64
bjlvxin@bjlvxin-Vostro-270:/sourcecode/go/work/src/github.com/tiger/mygate/cmd$ ./build.sh
bjlvxin@bjlvxin-Vostro-270:/sourcecode/go/work/src/github.com/tiger/mygate/cmd$ ./mygate 
panic: http: multiple registrations for /debug/requests

goroutine 1 [running]:
net/http.(*ServeMux).Handle(0x152e9c0, 0xe32ad5, 0xf, 0x13617e0, 0xe64468)
    /software/servers/go1.9.2/src/net/http/server.go:2270 +0x627
net/http.(*ServeMux).HandleFunc(0x152e9c0, 0xe32ad5, 0xf, 0xe64468)
    /software/servers/go1.9.2/src/net/http/server.go:2302 +0x55
net/http.HandleFunc(0xe32ad5, 0xf, 0xe64468)
    /software/servers/go1.9.2/src/net/http/server.go:2314 +0x4b
golang.org/x/net/trace.init.0()
    /sourcecode/go/work/src/golang.org/x/net/trace/trace.go:115 +0x42
golang.org/x/net/trace.init()
    <autogenerated>:1 +0x1cd
google.golang.org/grpc.init()
    <autogenerated>:1 +0x9b
vitess.io/vitess/go/vt/callinfo.init()
    <autogenerated>:1 +0x53
github.com/tiger/mygate/gate.init()
    <autogenerated>:1 +0xaa
main.init()
    <autogenerated>:1 +0x4e

從上面的輸出中可以看到优炬,將golang的版本改為1.9.0之后,打印出了更多的錯(cuò)誤堆棧信息厅贪,而且可以看出,是在執(zhí)行g(shù)ate.init()方法的時(shí)候?qū)е铝藛?wèn)題雅宾。

方案二:設(shè)置環(huán)境變量:export GOTRACEBACK=system

通過(guò)研究官方文檔养涮,發(fā)現(xiàn)可以通過(guò)設(shè)置環(huán)境變量GOTRACEBACK來(lái)控制Golang panic stack trace輸出的信息的多少葵硕。說(shuō)明如下:
環(huán)境變量GOTRACEBACK可以控制Go程序由于不可恢復(fù)的panic或者未預(yù)料到的其他運(yùn)行時(shí)異常而產(chǎn)生的錯(cuò)誤堆棧輸出的信息的多少。默認(rèn)情況下(single)贯吓,當(dāng)產(chǎn)生錯(cuò)誤的時(shí)候懈凹,只會(huì)打印出異常goroutine的異常堆棧,當(dāng)不存在當(dāng)前goroutine或者是由于runtime內(nèi)部的錯(cuò)誤導(dǎo)致的panic悄谐,則會(huì)打印出所有g(shù)oroutine的堆棧介评。 GOTRACEBACK的設(shè)置值有幾種,下面分別說(shuō)明:
export GOTRACEBACK=none :完全省略panic的 stack traces 爬舰。
export GOTRACEBACK=single (默認(rèn)值)只打印當(dāng)前goroutine的部分stack traces们陆。當(dāng)不存在當(dāng)前goroutine或者是由于runtime內(nèi)部的錯(cuò)誤導(dǎo)致的panic,則會(huì)打印出所有g(shù)oroutine的堆棧情屹。
export GOTRACEBACK=all :打印用戶創(chuàng)建的所有g(shù)oroutine的stack trace坪仇。
export GOTRACEBACK=system :與all的行為很像,只不過(guò)會(huì)將runtime的goroutine的stace trace也打出來(lái)垃你,并且還會(huì)顯示出runtime內(nèi)部創(chuàng)建的所有g(shù)oroutine椅文。
export GOTRACEBACK=crash:與“system”的行為很像,只不過(guò)當(dāng)程序crash的時(shí)候不是直接退出惜颇,而是可以按照操作系統(tǒng)指定的方式進(jìn)行后續(xù)處理皆刺。
例如,在Unix操作系統(tǒng)中凌摄,crash會(huì)發(fā)送一個(gè)SIGABRT信號(hào)觸發(fā)core dump羡蛾。由于歷史原因,當(dāng)將系統(tǒng)環(huán)境變量GOTRACEBACK設(shè)置為:0, 1, 和 2 的時(shí)候望伦,分別代表none, all和system林说。通過(guò)包runtime/debug package中的方法SetTraceback,也可以設(shè)置相應(yīng)的GOTRACEBACK的值屯伞,進(jìn)而控制輸出的stack trace的內(nèi)容的多少腿箩,但是通過(guò)該方法,不能夠設(shè)置比系統(tǒng)環(huán)境變量的level更低的值劣摇。而level的高低順序?yàn)椋?br> none<single<all<system<crash
具體SetTraceback方法的時(shí)候可以參考: https://golang.org/pkg/runtime/debug/#SetTraceback.

#在~/.bashrc文件中添加環(huán)境變量GOTRACEBACK:export GOTRACEBACK=system
bjlvxin@bjlvxin-Vostro-270:/sourcecode/go/work/src/github.com/tiger/mygate/cmd$ vim ~/.bashrc
bjlvxin@bjlvxin-Vostro-270:/sourcecode/go/work/src/github.com/tiger/mygate/cmd$ source ~/.bashrc
bjlvxin@bjlvxin-Vostro-270:/sourcecode/go/work/src/github.com/tiger/mygate/cmd$ ./build.sh 
bjlvxin@bjlvxin-Vostro-270:/sourcecode/go/work/src/github.com/tiger/mygate/cmd$ ./mygate 
panic: http: multiple registrations for /debug/requests

goroutine 1 [running]:
panic(0xc2e240, 0xc4200315d0)
    /software/servers/go1.10.3/src/runtime/panic.go:551 +0x3c1 fp=0xc42007bdd8 sp=0xc42007bd38 pc=0x42b681
net/http.(*ServeMux).Handle(0x149f340, 0xdbfe9b, 0xf, 0xe524a0, 0xdf2318)
    /software/servers/go1.10.3/src/net/http/server.go:2353 +0x239 fp=0xc42007be38 sp=0xc42007bdd8 pc=0x8642c9
net/http.(*ServeMux).HandleFunc(0x149f340, 0xdbfe9b, 0xf, 0xdf2318)
    /software/servers/go1.10.3/src/net/http/server.go:2368 +0x55 fp=0xc42007be70 sp=0xc42007be38 pc=0x864375
net/http.HandleFunc(0xdbfe9b, 0xf, 0xdf2318)
    /software/servers/go1.10.3/src/net/http/server.go:2380 +0x4b fp=0xc42007bea0 sp=0xc42007be70 pc=0x8643db
golang.org/x/net/trace.init.0()
    /sourcecode/go/work/src/golang.org/x/net/trace/trace.go:115 +0x42 fp=0xc42007bec8 sp=0xc42007bea0 pc=0x9d3c92
golang.org/x/net/trace.init()
    <autogenerated>:1 +0x158 fp=0xc42007bef0 sp=0xc42007bec8 pc=0x9d9088
google.golang.org/grpc.init()
    <autogenerated>:1 +0x9b fp=0xc42007bf28 sp=0xc42007bef0 pc=0xa39eeb
vitess.io/vitess/go/vt/callinfo.init()
    <autogenerated>:1 +0x53 fp=0xc42007bf38 sp=0xc42007bf28 pc=0xa3c5d3
github.com/tiger/mygate/gate.init()
    <autogenerated>:1 +0xaa fp=0xc42007bf78 sp=0xc42007bf38 pc=0xba060a
main.init()
    <autogenerated>:1 +0x4e fp=0xc42007bf88 sp=0xc42007bf78 pc=0xba21ae
runtime.main()
    /software/servers/go1.10.3/src/runtime/proc.go:186 +0x1ca fp=0xc42007bfe0 sp=0xc42007bf88 pc=0x42d34a
runtime.goexit()
    /software/servers/go1.10.3/src/runtime/asm_amd64.s:2361 +0x1 fp=0xc42007bfe8 sp=0xc42007bfe0 pc=0x457fa1

goroutine 2 [force gc (idle)]:
runtime.gopark(0xdf2ed0, 0x149d570, 0xdc053a, 0xf, 0xdf2d14, 0x1)
    /software/servers/go1.10.3/src/runtime/proc.go:291 +0x11a fp=0xc420058768 sp=0xc420058748 pc=0x42d7ea
runtime.goparkunlock(0x149d570, 0xdc053a, 0xf, 0x14, 0x1)
    /software/servers/go1.10.3/src/runtime/proc.go:297 +0x5e fp=0xc4200587a8 sp=0xc420058768 pc=0x42d89e
runtime.forcegchelper()
    /software/servers/go1.10.3/src/runtime/proc.go:248 +0xcc fp=0xc4200587e0 sp=0xc4200587a8 pc=0x42d62c
runtime.goexit()
    /software/servers/go1.10.3/src/runtime/asm_amd64.s:2361 +0x1 fp=0xc4200587e8 sp=0xc4200587e0 pc=0x457fa1
created by runtime.init.4
    /software/servers/go1.10.3/src/runtime/proc.go:237 +0x35

goroutine 3 [GC sweep wait]:
runtime.gopark(0xdf2ed0, 0x149dea0, 0xdbe7ab, 0xd, 0x420014, 0x1)
    /software/servers/go1.10.3/src/runtime/proc.go:291 +0x11a fp=0xc420058f60 sp=0xc420058f40 pc=0x42d7ea
runtime.goparkunlock(0x149dea0, 0xdbe7ab, 0xd, 0x14, 0x1)
    /software/servers/go1.10.3/src/runtime/proc.go:297 +0x5e fp=0xc420058fa0 sp=0xc420058f60 pc=0x42d89e
runtime.bgsweep(0xc4200440e0)
    /software/servers/go1.10.3/src/runtime/mgcsweep.go:52 +0xa3 fp=0xc420058fd8 sp=0xc420058fa0 pc=0x420073
runtime.goexit()
    /software/servers/go1.10.3/src/runtime/asm_amd64.s:2361 +0x1 fp=0xc420058fe0 sp=0xc420058fd8 pc=0x457fa1
created by runtime.gcenable
    /software/servers/go1.10.3/src/runtime/mgc.go:216 +0x58

goroutine 4 [finalizer wait]:
runtime.gopark(0xdf2ed0, 0x14bd6a8, 0xdbf876, 0xe, 0x14, 0x1)
    /software/servers/go1.10.3/src/runtime/proc.go:291 +0x11a fp=0xc420059718 sp=0xc4200596f8 pc=0x42d7ea
runtime.goparkunlock(0x14bd6a8, 0xdbf876, 0xe, 0x14, 0x1)
    /software/servers/go1.10.3/src/runtime/proc.go:297 +0x5e fp=0xc420059758 sp=0xc420059718 pc=0x42d89e
runtime.runfinq()
    /software/servers/go1.10.3/src/runtime/mfinal.go:175 +0xad fp=0xc4200597e0 sp=0xc420059758 pc=0x41711d
runtime.goexit()
    /software/servers/go1.10.3/src/runtime/asm_amd64.s:2361 +0x1 fp=0xc4200597e8 sp=0xc4200597e0 pc=0x457fa1
created by runtime.createfing
    /software/servers/go1.10.3/src/runtime/mfinal.go:156 +0x62

goroutine 5 [chan receive]:
runtime.gopark(0xdf2ed0, 0xc4200e4058, 0xdbe01e, 0xc, 0xc420049317, 0x3)
    /software/servers/go1.10.3/src/runtime/proc.go:291 +0x11a fp=0xc420059e88 sp=0xc420059e68 pc=0x42d7ea
runtime.goparkunlock(0xc4200e4058, 0xdbe01e, 0xc, 0x17, 0x3)
    /software/servers/go1.10.3/src/runtime/proc.go:297 +0x5e fp=0xc420059ec8 sp=0xc420059e88 pc=0x42d89e
runtime.chanrecv(0xc4200e4000, 0xc420059fb0, 0xc4200e8001, 0xc4200e4000)
    /software/servers/go1.10.3/src/runtime/chan.go:518 +0x2f2 fp=0xc420059f60 sp=0xc420059ec8 pc=0x406082
runtime.chanrecv2(0xc4200e4000, 0xc420059fb0, 0x0)
    /software/servers/go1.10.3/src/runtime/chan.go:405 +0x2b fp=0xc420059f90 sp=0xc420059f60 pc=0x405d7b
github.com/golang/glog.(*loggingT).flushDaemon(0x149fc20)
    /sourcecode/go/work/src/github.com/golang/glog/glog.go:882 +0x8b fp=0xc420059fd8 sp=0xc420059f90 pc=0x589ebb
runtime.goexit()
    /software/servers/go1.10.3/src/runtime/asm_amd64.s:2361 +0x1 fp=0xc420059fe0 sp=0xc420059fd8 pc=0x457fa1
created by github.com/golang/glog.init.0
    /sourcecode/go/work/src/github.com/golang/glog/glog.go:410 +0x203

goroutine 18 [syscall]:
runtime.notetsleepg(0x14a3e20, 0x6fc233bba, 0x0)
    /software/servers/go1.10.3/src/runtime/lock_futex.go:227 +0x42 fp=0xc420054760 sp=0xc420054730 pc=0x410d82
runtime.timerproc(0x14a3e00)
    /software/servers/go1.10.3/src/runtime/time.go:261 +0x2e7 fp=0xc4200547d8 sp=0xc420054760 pc=0x4493a7
runtime.goexit()
    /software/servers/go1.10.3/src/runtime/asm_amd64.s:2361 +0x1 fp=0xc4200547e0 sp=0xc4200547d8 pc=0x457fa1
created by runtime.(*timersBucket).addtimerLocked
    /software/servers/go1.10.3/src/runtime/time.go:160 +0x107

goroutine 6 [syscall]:
runtime.notetsleepg(0x14bdcc0, 0xffffffffffffffff, 0x0)
    /software/servers/go1.10.3/src/runtime/lock_futex.go:227 +0x42 fp=0xc42005a780 sp=0xc42005a750 pc=0x410d82
os/signal.signal_recv(0x0)
    /software/servers/go1.10.3/src/runtime/sigqueue.go:139 +0xa6 fp=0xc42005a7a8 sp=0xc42005a780 pc=0x4414e6
os/signal.loop()
    /software/servers/go1.10.3/src/os/signal/signal_unix.go:22 +0x22 fp=0xc42005a7e0 sp=0xc42005a7a8 pc=0x99f782
runtime.goexit()
    /software/servers/go1.10.3/src/runtime/asm_amd64.s:2361 +0x1 fp=0xc42005a7e8 sp=0xc42005a7e0 pc=0x457fa1
created by os/signal.init.0
    /software/servers/go1.10.3/src/os/signal/signal_unix.go:28 +0x41

從上面的輸出中可以看到珠移,除了打印出了方案一中所看到的錯(cuò)誤堆棧信息,還打印了其他的goroutine的堆棧信息末融。

總結(jié)

不知道為什么钧惧,默認(rèn)的情況下golang1.10.3打印的錯(cuò)誤堆棧信息要比1.9.0的錯(cuò)誤堆棧信息要少,我也沒(méi)有查看golang具體的源代碼勾习,有興趣的同學(xué)浓瞪,可以研究下golang的源代碼。但是我們可以知道有兩種方法可以得到更多的goroutine堆棧信息:
(1)使用golang 1.9.0版本
(2)export GOTRACEBACK=system

參考

https://golang.org/pkg/runtime/
https://golang.org/pkg/runtime/debug/#SetTraceback


呂信個(gè)人原創(chuàng)巧婶,轉(zhuǎn)載請(qǐng)注明出處

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乾颁,一起剝皮案震驚了整個(gè)濱河市涂乌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌英岭,老刑警劉巖湾盒,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異诅妹,居然都是意外死亡罚勾,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)吭狡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)尖殃,“玉大人,你說(shuō)我怎么就攤上這事赵刑》稚溃” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵般此,是天一觀的道長(zhǎng)蚪战。 經(jīng)常有香客問(wèn)我,道長(zhǎng)铐懊,這世上最難降的妖魔是什么邀桑? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮科乎,結(jié)果婚禮上壁畸,老公的妹妹穿的比我還像新娘。我一直安慰自己茅茂,他們只是感情好捏萍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著空闲,像睡著了一般令杈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碴倾,一...
    開(kāi)封第一講書(shū)人閱讀 51,775評(píng)論 1 307
  • 那天逗噩,我揣著相機(jī)與錄音,去河邊找鬼跌榔。 笑死异雁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的僧须。 我是一名探鬼主播纲刀,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼担平!你這毒婦竟也來(lái)了示绊?” 一聲冷哼從身側(cè)響起芥挣,我...
    開(kāi)封第一講書(shū)人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耻台,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體空另,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盆耽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扼菠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摄杂。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖循榆,靈堂內(nèi)的尸體忽然破棺而出析恢,到底是詐尸還是另有隱情,我是刑警寧澤秧饮,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布映挂,位于F島的核電站,受9級(jí)特大地震影響盗尸,放射性物質(zhì)發(fā)生泄漏柑船。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一泼各、第九天 我趴在偏房一處隱蔽的房頂上張望鞍时。 院中可真熱鬧,春花似錦扣蜻、人聲如沸逆巍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)锐极。三九已至,卻和暖如春吮旅,著一層夾襖步出監(jiān)牢的瞬間溪烤,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工庇勃, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留檬嘀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓责嚷,卻偏偏與公主長(zhǎng)得像鸳兽,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子罕拂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

推薦閱讀更多精彩內(nèi)容