调试 Go C 共享库问题:网络调用挂起
问题
Go 程序在调用 http.Post() 时遇到挂起同时构建为 C 共享库 (-buildmode=c-shared)。但是,标准可执行二进制文件 (GOOS=linux GOARCH=amd64 ./example) 返回正确的值。
问题根源
问题的出现是因为在 C 语言时加载了 Go 运行时共享库由父进程加载。但是,当在分叉子进程中使用该库时,Go 运行时无法正确加载,从而导致不可预测的行为和挂起调用。
调试步骤
-
检查使用 strace 进行系统调用: strace 工具可以显示进程正在进行的系统调用。例如,运行 strace -fp PID 可能会显示对 futex 和 Post 操作的调用,例如 futex(0x7f618b2c1cd0, FUTEX_WAKE, 1) 和 Post()。
-
向 HTTP 服务器添加分析: 要收集有关程序挂起时的状态信息,请使用 http.ListenAndServe("localhost:6060", nil) 将分析添加到 HTTP 服务器。这将在端口 6060 上运行分析器,可以检查该分析器以确定挂起的原因。
解决方案
解决方案涉及控制子进程中 Go 运行时的加载过程。为此:
- 在子进程 fork 后使用 dlopen 加载 Go 共享库。
- 在子进程中使用 dlsym 访问 Go 库中的符号。
通过在子进程中显式加载Go运行时,保证运行时正确初始化并成功进行网络调用。
以上是## 为什么我的 Go C 共享库在分叉子进程中的网络调用上挂起?的详细内容。更多信息请关注PHP中文网其他相关文章!