我正在用 cgo 包装一个 C 库以供普通 Go 代码使用。
我的问题是我想将错误字符串传播到 Go API,但是有问题的 C 库通过线程本地存储提供错误字符串;有一个全局get_error()调用返回指向线程本地字符数据的指针。
我最初的计划是通过 cgo 调用 C,检查调用是否返回错误,如果是,则将错误字符串包装起来C.GoString,将其从原始字符指针转换为 Go 字符串。它看起来像C.GoString(C.get_error()).
我在这里预见到的问题是 C 中的 TLS 在本机 OS 线程级别上工作,但据我了解,调用 Go 代码将来自潜在的 N 个 goroutine 之一,这些 goroutine 在某个数量的底层本地线程中多路复用由 Go 调度程序管理的线程池。
我害怕遇到这样一种情况:我调用了 C 例程,然后在 C 例程返回之后,但在我复制错误字符串之前,Go 调度程序决定将当前的 goroutine 换成另一个。当原始的 goroutine 被换回时,据我所知,它可能位于不同的本地线程上,但即使它被换回同一个线程,在此期间运行的任何 goroutine 都可能改变了状态的 TLS,导致我为不相关的调用加载错误字符串。
我的问题是:
这是一个合理的担忧吗?我是否误解了 go 调度程序,或者它与 cgo 交互的方式,这会导致这不是问题?
如果这是一个合理的问题,我该如何解决?
cgo 设法将 errno 值传播回调用 Go 代码,这些代码也存储在 TLS 中,这让我认为必须有一种安全的方法来做到这一点。
我想不出 C 代码本身可以被 go 调度程序抢占的方式,所以我应该引入一个包装 C 函数并让 IT 进行必要的调用,然后在返回 goland 之前有条件地复制错误字符串?
我对任何允许我将错误字符串传播到 Go 的其余部分的解决方案感兴趣,但我希望避免任何需要我序列化围绕 TLS 的访问的解决方案,因为添加一个锁只是为了抓取一个错误字符串对我来说似乎非常不幸。
提前致谢!
拉风的咖菲猫
相关分类