如何调试 C 共享库(用 Go 编写)——它挂在网络调用上

Jan*_*raj 3 c shared-libraries stack-trace go

使用http.Post() 进行编码。如果我构建exe,就可以了。如果我构建 C 共享库-buildmode=c-shared,它会挂在 https.Post() 上。

我试过strace -fp PID

futex(0x7f618b2c1cd0, FUTEX_WAKE, 1)    = 0
futex(0xc820022110, FUTEX_WAIT, 0, NULL
Run Code Online (Sandbox Code Playgroud)

我试图添加分析器:

http.ListenAndServe("localhost:6060", nil)
http.Post()
Run Code Online (Sandbox Code Playgroud)

但是它再次挂在 http.Post 上,并且分析器也被阻止了(它正在侦听,但不是来自 6060 端口的响应)。我已经发送了 SIGQUIT 信号 - 堆栈跟踪:

SIGQUIT: quit
PC=0x7f0cad5c9081 m=1

goroutine 0 [idle]:
runtime.futex(0xc820022110, 0x0, 0x0, 0x0, 0x7f0c00000000, 0x7f0cad577879, 0x0, 0x0, 0x7f0cad577ae8, 0xc820022110, ...)
        /usr/local/go/src/runtime/sys_linux_amd64.s:288 +0x21
runtime.futexsleep(0xc820022110, 0xc800000000, 0xffffffffffffffff)
        /usr/local/go/src/runtime/os1_linux.go:39 +0x53
runtime.notesleep(0xc820022110)
        /usr/local/go/src/runtime/lock_futex.go:142 +0xa8
runtime.stoplockedm()
        /usr/local/go/src/runtime/proc1.go:1268 +0xb2
runtime.schedule()
        /usr/local/go/src/runtime/proc1.go:1590 +0x72
runtime.park_m(0xc820000600)
        /usr/local/go/src/runtime/proc1.go:1698 +0x191
runtime.mcall(0x7f0cad5c722a)
        /usr/local/go/src/runtime/asm_amd64.s:204 +0x53

goroutine 17 [IO wait, locked to thread]:
runtime.gopark(0x7f0cada4a878, 0x7f0ca594b198, 0x7f0cad993b20, 0x7, 0x1b, 0x5)
        /usr/local/go/src/runtime/proc.go:185 +0x169 fp=0xc820041868 sp=0xc820041840
runtime.netpollblock(0x7f0ca594b170, 0x72, 0x7f0cac21e050)
        /usr/local/go/src/runtime/netpoll.go:338 +0x160 fp=0xc8200418b0 sp=0xc820041868
net.runtime_pollWait(0x7f0ca594b170, 0x72, 0xc82000a1c0)
        /usr/local/go/src/runtime/netpoll.go:157 +0x62 fp=0xc8200418d0 sp=0xc8200418b0
net.(*pollDesc).Wait(0xc82011c140, 0x72, 0x0, 0x0)
        /usr/local/go/src/net/fd_poll_runtime.go:73 +0x3c fp=0xc8200418f0 sp=0xc8200418d0
net.(*pollDesc).WaitRead(0xc82011c140, 0x0, 0x0)
        /usr/local/go/src/net/fd_poll_runtime.go:78 +0x38 fp=0xc820041918 sp=0xc8200418f0
net.(*netFD).accept(0xc82011c0e0, 0x0, 0x7f0ca594b268, 0xc8200b4440)
        /usr/local/go/src/net/fd_unix.go:408 +0x27e fp=0xc820041a18 sp=0xc820041918
net.(*TCPListener).AcceptTCP(0xc8200b8050, 0xc820041ab0, 0x0, 0x0)
        /usr/local/go/src/net/tcpsock_posix.go:254 +0x4f fp=0xc820041a78 sp=0xc820041a18
net/http.tcpKeepAliveListener.Accept(0xc8200b8050, 0x0, 0x0, 0x0, 0x0)
        /usr/local/go/src/net/http/server.go:2135 +0x43 fp=0xc820041ab0 sp=0xc820041a78
net/http.(*Server).Serve(0xc8200b20c0, 0x7f0ca594b230, 0xc8200b8050, 0x0, 0x0)
        /usr/local/go/src/net/http/server.go:1887 +0xb5 fp=0xc820041b98 sp=0xc820041ab0
net/http.(*Server).ListenAndServe(0xc8200b20c0, 0x0, 0x0)
        /usr/local/go/src/net/http/server.go:1877 +0x138 fp=0xc820041c28 sp=0xc820041b98
net/http.ListenAndServe(0x7f0cad9a6ae0, 0xe, 0x0, 0x0, 0x0, 0x0)
        /usr/local/go/src/net/http/server.go:1967 +0x91 fp=0xc820041c50 sp=0xc820041c28
main.Code(0xc8201122a0, 0x0, 0x0, 0x0, 0x0)
        /opt/gopath/src/github.com/jangaraj/zabbix-module/zabbix_module.go:152 +0x94 fp=0xc820041d58 sp=0xc820041c50
github.com/cavaliercoder/g2z.route_item(0x7ffe7bc803e0, 0x7ffe7bc80c90, 0x0)
        /opt/gopath/src/github.com/cavaliercoder/g2z/router.go:65 +0xc2a fp=0xc820041ed0 sp=0xc820041d58
runtime.call32(0x0, 0x7ffe7bc802d8, 0x7ffe7bc80360, 0x18)
        /usr/local/go/src/runtime/asm_amd64.s:437 +0x40 fp=0xc820041ef8 sp=0xc820041ed0
runtime.cgocallbackg1()
        /usr/local/go/src/runtime/cgocall.go:252 +0x110 fp=0xc820041f30 sp=0xc820041ef8
runtime.cgocallbackg()
        /usr/local/go/src/runtime/cgocall.go:177 +0xd9 fp=0xc820041f90 sp=0xc820041f30
runtime.cgocallback_gofunc(0x0, 0x0, 0x0)
        /usr/local/go/src/runtime/asm_amd64.s:801 +0x5d fp=0xc820041fa0 sp=0xc820041f90
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1696 +0x1 fp=0xc820041fa8 sp=0xc820041fa0

goroutine 18 [syscall, locked to thread]:
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1696 +0x1

goroutine 5 [chan receive]:
github.com/golang/glog.(*loggingT).flushDaemon(0x7f0cadd99bc0)
        /opt/gopath/src/github.com/golang/glog/glog.go:882 +0x69
created by github.com/golang/glog.init.1
        /opt/gopath/src/github.com/golang/glog/glog.go:410 +0x299

rax    0xca
rbx    0x0
rcx    0xffffffffffffffff
rdx    0x0
rdi    0xc820022110
rsi    0x0
rbp    0x1
rsp    0x7ffe7bc801a8
r8     0x0
r9     0x0
r10    0x0
r11    0x286
r12    0x4
r13    0x7f0cada47090
r14    0xd
r15    0x8
rip    0x7f0cad5c9081
rflags 0x286
cs     0x33
fs     0x0
gs     0x0
Run Code Online (Sandbox Code Playgroud)

如何调试/解决这个问题?代码看起来不错 - 标准的可执行二进制文件返回正确的值。只有 C 共享库版本有一些问题。共享库中的另一种方法,不使用 http.post()/net.Dial() 是可以的。

原问题:https : //github.com/cavaliercoder/g2z/issues/5

rmo*_*njo 5

好的,我为我的用例解决了这个问题,您可能处于类似的情况。

当您将 Go 共享库链接到 C 或 C++ 应用程序时,Go 运行时会在您启动应用程序时加载(您可以验证这一点,func init()例如,在您启动应用程序时直接调用它)。然后,如果你 fork 一个进程并使用 Go 库,你将有不可预测的行为。基本上,你必须在 fork 之后加载 Go 共享库,并且一旦你 fork 就不能依赖它。使用dlopendlsym将允许您控制 Go 运行时何时被加载。