我正在使用本机 linux C 二进制文件,它有一个相当昂贵的初始化调用,我想在应用程序启动时执行一次。这个调用应该在内部打开一堆文件句柄供以后使用。当我从 Go 调用这个昂贵的初始化 C 函数时,它成功完成并正确打开文件,但这些句柄仅在调用 C 函数期间打开!这意味着当我从 Go 中针对同一个库调用连续的 C 函数时,文件句柄不再打开并且调用失败。我已经使用 lsof 命令验证了这一点。有趣的是,当初始化调用以及对后续行为的调用被组合成一个 C 函数时,然后从 Go 调用该函数,文件将打开并保持打开状态,从而成功完成所有所需的功能。
是否存在某种未记录的 cgo 行为,即在从 Go 多次调用 C 函数之间“清理”、关闭甚至泄漏文件句柄或其他有状态资源?如果是这样,这种行为是否可配置?我们无权访问此库的源代码。
此外,我已经验证这与线程本地存储无关。调用runtime.LockOSThread()
没有效果,我们已经验证了在控制权从 C 返回到调用 Go 代码后文件已关闭。
这是我想编写的 Go 代码示例:
// Go code:
func main() {
C.Initialize()
C.do_stuff() // internal state is already cleaned up! This call fails as a result. :(
}
这是一个同时调用初始化和行为的 C 函数示例。这个“包装”函数是从 Go 调用的:
// C code:
void DoEverything(void)
{
Initialize();
do_stuff(); // succeeds because all internal state is intact (not cleaned up).
}