关于Interrupted system call 报错

Socket编程或者其他的一些慢速系统调用中,我们经常会碰到“interrupted system call”的问题。

这些系统调用包括:

  • 长时间读取磁盘,
  • 等待网络连接i.e. Accept,
  • 阻塞的系统调用, i.e.Read/Write epoll_wait/kevent

这是因为系统调用在执行过程中有可能收到来自外部的信号中断,那么该系统调用就会返回一个EINTR错误,我们的程序需要对该错误做相应的处理。

处理的方式有三种:

这里我们附加的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

posted @ 2024-05-29 13:30  zongzw  阅读(1236)  评论(0)    收藏  举报