如何使用 dlv 调试 smartraiden

#使用 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 调试

  1. 出了问题,但是没有崩溃,直接 attach 即可
  2. 出了问题,但是崩溃了,可以提前设置断点

三 dlv attach

attach 成功以后,程序会停止运行

goroutines -s 查看所有 goroutine 的栈

解决问题

  1. 如果觉得某个 goroutine 有问题
    goroutine 108 就可以切换到这个 goroutine, 进行调试
  2. 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
  3. 在栈之间移动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)
  4. 查看局部变量
    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)