最近有项目要用到cgo, 对接外援写的so的库,期间cgo的代码总是不经意的崩溃啊,异常退出,种种鬼怪。
cgo panic 错误
// 刚开始对接的时候,调用cgo的程序会抛出panic, 但是并不退出主程序。处理方法:
- 在goroutine内defer处理此panic
- recover后
- 进行相应的错误处理
- go的主程序继续运行
整个程序突然退出
怀疑是别人给kill了,signal处理
c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) go func() { select { case sig := <- c: log.Println(fmt.Sprintf("got signal from:%v", sig)) } }() //当程序由于signal信号退出的时候,就可以捕捉到了,ctrl+c, 或者kill的方式都可以
使用dvl调试程序 (测试cgo exit时, dvl可不可以捕捉到)
- dlv 安装:
- go get github.com/derekparker/delve
- cd $GOPATH/src/github.com/derekparker/delve && make install
- 在 $GOPATH/bin/目录下就会产生dlv程序,可以直接运行
- 接下来就可以用dlv代替gdb来调试golang的程序了,很方便吧
测试证明,cgo程序退出时,go的主程序也会退出
fmt.Println("version is", C.call_version())
time.Sleep(time.Duration(2) * time.Second)
fmt.Println("sleep 2 seconds, call c exit")
C.call_exit()
fmt.Println(fmt.Sprintf("go main function is running"))
version is 16909060
sleep 2 seconds, call c exit
c call to exit program
exit status 255
因为并未打印最后一句啊,所以panic根本就没有用
产生coredump文件,查堆栈
将GOTRACEBACK环境变量设置为crack模式,并开启core dump。 在/etc/profile中添加
GOTRACEBACK=crash
开启core dump: ulimit 设置为unlimited, 并设置-c 大于0
调研cgo退出的几种方式:
- throw 异常
- 边界溢出