Golang 1.14beta1版本使用中遇到的问题

Golang 1.14beta1版本使用中遇到的问题 我正在尝试将我们的应用从 Go 1.11 升级到 Go 1.14。由于 1.14 beta1 刚刚发布,我打算尝试一下。我发现,在这个版本中,zmq 内部的系统调用会因 EINTR 而失败。这通常发生在系统调用被信号中断的情况下。我原以为 Go 运行时会强制执行 SA_RESTART,是不是 1.14 版本中这方面的某些功能出现了问题?

2 回复

有一个专门的地方可以报告 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 仓库中报告问题,或者查看是否有其他开发者遇到类似情况。

回到顶部