Socket编程或者其他的一些慢速系统调用中,我们经常会碰到“interrupted system call”的问题。
这些系统调用包括:
- 长时间读取磁盘,
- 等待网络连接i.e. Accept,
- 阻塞的系统调用, i.e.Read/Write epoll_wait/kevent
这是因为系统调用在执行过程中有可能收到来自外部的信号中断,那么该系统调用就会返回一个EINTR错误,我们的程序需要对该错误做相应的处理。
处理的方式有三种:
- 人为重启被中断的系统调用,不同的系统调用的重启方法不同。多数实操方法就是发现该错误时用for loop 重试
- 设置SA_RESTART属性(可能对某些系统调用无效)https://www.jianshu.com/p/53dde0c19d9b
- 忽略信号(让系统不产生信号中断)https://www.jianshu.com/p/53dde0c19d9b
这里我们附加的golang 代码 是 人为重启中断的系统调用:
func (np *KqueuePoller) readFd(fd int) ([]byte, error) {
b := []byte{}
for {
buf := make([]byte, BUFF_SIZE)
n, err := syscall.Read(fd, buf)
if err != nil {
if err == syscall.EAGAIN {
break
} else if err == syscall.EINTR {
// 读取socket过程中碰到interrupted system call,直接跳转下一次for loop
log.Printf("interrupted while reading")
} else {
return nil, err
}
} else if n == 0 {
log.Printf("closing socket: %d", fd)
return nil, io.EOF
} else {
b = append(b, buf[:n]...)
}
}
return b, nil
}
以上代码来自 Unix环境下的kqueue/kevent IO多路复用的golang实现:https://github.com/zongzw-learn/learn-go/blob/master/basics/tcp-poller/netpoller.go#L163
标签:调用,err,系统,system,else,call,报错 From: https://www.cnblogs.com/zongzw/p/18220074