Golang 1.14beta1版本使用中遇到的问题
Golang 1.14beta1版本使用中遇到的问题 我正在尝试将我们的应用从 Go 1.11 升级到 Go 1.14。由于 1.14 beta1 刚刚发布,我打算尝试一下。我发现,在这个版本中,zmq 内部的系统调用会因 EINTR 而失败。这通常发生在系统调用被信号中断的情况下。我原以为 Go 运行时会强制执行 SA_RESTART,是不是 1.14 版本中这方面的某些功能出现了问题?
有一个专门的地方可以报告 go1.14beta1 的问题。
请使用问题跟踪器报告任何问题: 登录 GitHub · GitHub
更多关于Golang 1.14beta1版本使用中遇到的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在 Go 1.14 beta1 中,运行时对信号处理的行为确实有所调整,这可能导致某些系统调用因 EINTR 而失败。具体来说,Go 1.14 引入了对非协作式抢占的支持,这涉及到更多的信号使用,可能会影响像 zmq 这样的库,尤其是当它们进行阻塞系统调用时。
在之前的版本中,Go 运行时确实会为某些信号设置 SA_RESTART 标志,以确保系统调用在中断后自动重启。但在 1.14 中,由于抢占机制的改变,信号处理可能不再默认启用 SA_RESTART,导致系统调用返回 EINTR 错误。这不是一个 bug,而是设计上的变化,旨在提高调度的响应性。
对于你的情况,zmq 库可能依赖于系统调用在中断后自动重启。当 SA_RESTART 未设置时,系统调用会失败并返回 EINTR,需要手动重试。你可以通过包装系统调用来处理 EINTR,或者检查 zmq 库是否有更新以兼容 Go 1.14。
以下是一个简单的示例,展示如何在 Go 中处理可能返回 EINTR 的系统调用(以 syscall.Read 为例):
package main
import (
"fmt"
"syscall"
)
func readWithRetry(fd int, buf []byte) (n int, err error) {
for {
n, err = syscall.Read(fd, buf)
if err != syscall.EINTR {
break
}
// 如果是 EINTR,继续重试
}
return n, err
}
func main() {
// 示例:使用 readWithRetry 来读取文件描述符
// 假设 fd 是一个有效的文件描述符
fd := 0 // 替换为实际的文件描述符
buf := make([]byte, 1024)
n, err := readWithRetry(fd, buf)
if err != nil {
fmt.Printf("Read failed: %v\n", err)
} else {
fmt.Printf("Read %d bytes\n", n)
}
}
在这个示例中,readWithRetry 函数会持续重试 syscall.Read,直到错误不是 EINTR。你可以根据类似的方式调整 zmq 相关的代码,或者等待库的更新。
另外,建议关注 Go 1.14 的官方发布说明和问题跟踪器,以获取更多关于信号处理变化的详细信息。如果问题持续存在,可以考虑在 Go 的 GitHub 仓库中报告问题,或者查看是否有其他开发者遇到类似情况。

