使用 dlv 调试smartraiden
by 白振轩
对于程序运行过程中碰到的莫名其妙的问题,比如不明原因的阻塞,命令行 dlv 调试可能比 ide 调试效果更好
一 正常启动 smartraiden
./smartraiden --datadir=.smartraiden --api-address=0.0.0.0:5001 --listen-address=127.0.0.1:40001 --address="0x292650fee408320D888e06ed89D938294Ea42f99" --keystore-path ~/privnet3/keystore --registry-contract-address 0xf450955d87F23DF5DFc7297ed6DdDF4fb896Eff2 --password-file 123 --verbosity 5 --debug --conditionquit "{"QuitEvent":"EventSendRevealSecretBeforex"}" --debugcrash --eth-rpc-endpoint ws://127.0.0.1:8546
二 dlv 调试
- 出了问题,但是没有崩溃,直接 attach 即可
- 出了问题,但是崩溃了,可以提前设置断点
三 dlv attach
attach 成功以后,程序会停止运行
goroutines -s 查看所有 goroutine 的栈
解决问题
- 如果觉得某个 goroutine 有问题
goroutine 108
就可以切换到这个 goroutine, 进行调试 - bt 查看堆栈
(dlv) goroutine 108
Switched from 0 to 108 (thread 4644478)
(dlv) bt
0 0x000000000402f66a in runtime.gopark
at /usr/local/go/src/runtime/proc.go:292
1 0x000000000403f150 in runtime.selectgo
at /usr/local/go/src/runtime/select.go:392
2 0x0000000004608329 in github.com/SmartMeshFoundation/SmartRaiden/blockchain.(*Events).startListenEvent.func1
at /Volumes/dev/smdev2/src/github.com/SmartMeshFoundation/SmartRaiden/blockchain/events.go:275
3 0x000000000405c3d1 in runtime.goexit
at /usr/local/go/src/runtime/asm_amd64.s:2361
- 在栈之间移动up/down
up
up
会显示当前可以控制的栈
Frame 2: /Volumes/dev/smdev2/src/github.com/SmartMeshFoundation/SmartRaiden/blockchain/events.go:275 (PC: 4608329)
270: go func(name string) {
271: ch := be.LogChannelMap[name]
272: sub := be.Subscribes[name]
273: defer rpanic.PanicRecover(fmt.Sprintf("startListenEvent %s", name))
274: for {
=> 275: select {
276: case l, ok := <-ch:
277: if !ok {
278: //channel closed
279: return
280: }
(dlv)
- 查看局部变量
locals
可以显示目前所有的局部变量,也可以通过p 来打印具体的局部变量和全局变量.
(dlv) p ch
chan github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log {
qcount: 0,
dataqsiz: 10,
buf: *[10]struct github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log [
(*github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log)(0xc420335500),
(*github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log)(0xc4203355a8),
(*github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log)(0xc420335650),
(*github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log)(0xc4203356f8),
(*github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log)(0xc4203357a0),
(*github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log)(0xc420335848),
(*github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log)(0xc4203358f0),
(*github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log)(0xc420335998),
(*github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log)(0xc420335a40),
(*github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log)(0xc420335ae8),
],
elemsize: 168,
closed: 0,
elemtype: *runtime._type {
size: 168,
ptrdata: 56,
hash: 3390961113,
tflag: tflagUncommon|tflagExtraStar|tflagNamed,
align: 8,
fieldalign: 8,
kind: 25,
alg: *(*runtime.typeAlg)(0x5218c40),
gcdata: *72,
str: 56993,
ptrToThis: 1205856,},
sendx: 0,
recvx: 0,
recvq: waitq<github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log> {
first: *(*sudog<github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log>)(0xc4304ae4e0),
last: *(*sudog<github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log>)(0xc4304ae4e0),},
sendq: waitq<github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log> {
first: *sudog<github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log> nil,
last: *sudog<github.com/SmartMeshFoundation/SmartRaiden/vendor/github.com/ethereum/go-ethereum/core/types.Log> nil,},
lock: runtime.mutex {key: 0},}
(dlv)
可以看到 ch 这个 chann 目前没有任何数据,所以阻塞.
5. 也可以查看全局变量.也就是包级别的变量.
(dlv) p "github.com/SmartMeshFoundation/SmartRaiden/params".MobileMode
false
(dlv) p "github.com/SmartMeshFoundation/SmartRaiden/params".ChainID
*math/big.Int {
neg: false,
abs: math/big.nat len: 1, cap: 5, [8888],}
(dlv)