Catch EINTR

This commit is contained in:
Jason A. Donenfeld 2018-05-24 15:29:16 +02:00
parent 66f6ca3e4a
commit 2f2eca8947
11 changed files with 40 additions and 27 deletions

View file

@ -18,8 +18,8 @@
package main package main
import ( import (
"git.zx2c4.com/wireguard-go/rwcancel"
"errors" "errors"
"git.zx2c4.com/wireguard-go/rwcancel"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"net" "net"
"strconv" "strconv"
@ -563,7 +563,7 @@ func (bind *NativeBind) routineRouteListener(device *Device) {
var msgn int var msgn int
for { for {
msgn, _, _, _, err = unix.Recvmsg(bind.netlinkSock, msg[:], nil, 0) msgn, _, _, _, err = unix.Recvmsg(bind.netlinkSock, msg[:], nil, 0)
if err == nil || !rwcancel.ErrorIsEAGAIN(err) { if err == nil || !rwcancel.RetryAfterError(err) {
break break
} }
if !bind.netlinkCancel.ReadyRead() { if !bind.netlinkCancel.ReadyRead() {

View file

@ -7,9 +7,9 @@
package main package main
import ( import (
"git.zx2c4.com/wireguard-go/xchacha20poly1305"
"crypto/hmac" "crypto/hmac"
"crypto/rand" "crypto/rand"
"git.zx2c4.com/wireguard-go/xchacha20poly1305"
"golang.org/x/crypto/blake2s" "golang.org/x/crypto/blake2s"
"golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/chacha20poly1305"
"sync" "sync"

View file

@ -7,8 +7,8 @@
package main package main
import ( import (
"git.zx2c4.com/wireguard-go/replay"
"crypto/cipher" "crypto/cipher"
"git.zx2c4.com/wireguard-go/replay"
"sync" "sync"
"time" "time"
) )

View file

@ -7,8 +7,8 @@
package main package main
import ( import (
"git.zx2c4.com/wireguard-go/tun"
"fmt" "fmt"
"git.zx2c4.com/wireguard-go/tun"
"os" "os"
"os/signal" "os/signal"
"runtime" "runtime"

View file

@ -7,8 +7,8 @@
package main package main
import ( import (
"git.zx2c4.com/wireguard-go/tai64n"
"errors" "errors"
"git.zx2c4.com/wireguard-go/tai64n"
"golang.org/x/crypto/blake2s" "golang.org/x/crypto/blake2s"
"golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/poly1305" "golang.org/x/crypto/poly1305"

View file

@ -40,15 +40,16 @@ func NewRWCancel(fd int) (*RWCancel, error) {
return &rwcancel, nil return &rwcancel, nil
} }
/* https://golang.org/src/crypto/rand/eagain.go */ func RetryAfterError(err error) bool {
func ErrorIsEAGAIN(err error) bool {
if pe, ok := err.(*os.PathError); ok { if pe, ok := err.(*os.PathError); ok {
if errno, ok := pe.Err.(syscall.Errno); ok && errno == syscall.EAGAIN { err = pe.Err
}
if errno, ok := err.(syscall.Errno); ok {
switch errno {
case syscall.EAGAIN, syscall.EINTR:
return true return true
} }
}
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EAGAIN {
return true
} }
return false return false
} }
@ -86,7 +87,7 @@ func (rw *RWCancel) ReadyWrite() bool {
func (rw *RWCancel) Read(p []byte) (n int, err error) { func (rw *RWCancel) Read(p []byte) (n int, err error) {
for { for {
n, err := unix.Read(rw.fd, p) n, err := unix.Read(rw.fd, p)
if err == nil || !ErrorIsEAGAIN(err) { if err == nil || !RetryAfterError(err) {
return n, err return n, err
} }
if !rw.ReadyRead() { if !rw.ReadyRead() {
@ -98,7 +99,7 @@ func (rw *RWCancel) Read(p []byte) (n int, err error) {
func (rw *RWCancel) Write(p []byte) (n int, err error) { func (rw *RWCancel) Write(p []byte) (n int, err error) {
for { for {
n, err := unix.Write(rw.fd, p) n, err := unix.Write(rw.fd, p)
if err == nil || !ErrorIsEAGAIN(err) { if err == nil || !RetryAfterError(err) {
return n, err return n, err
} }
if !rw.ReadyWrite() { if !rw.ReadyWrite() {

View file

@ -7,14 +7,15 @@
package tun package tun
import ( import (
"git.zx2c4.com/wireguard-go/rwcancel"
"errors" "errors"
"fmt" "fmt"
"git.zx2c4.com/wireguard-go/rwcancel"
"golang.org/x/net/ipv6" "golang.org/x/net/ipv6"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"io/ioutil" "io/ioutil"
"net" "net"
"os" "os"
"syscall"
"unsafe" "unsafe"
) )
@ -54,8 +55,12 @@ func (tun *nativeTun) routineRouteListener(tunIfindex int) {
data := make([]byte, os.Getpagesize()) data := make([]byte, os.Getpagesize())
for { for {
retry:
n, err := unix.Read(tun.routeSocket, data) n, err := unix.Read(tun.routeSocket, data)
if err != nil { if err != nil {
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINTR {
goto retry
}
tun.errors <- err tun.errors <- err
return return
} }
@ -259,7 +264,7 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { func (tun *nativeTun) Read(buff []byte, offset int) (int, error) {
for { for {
n, err := tun.doRead(buff, offset) n, err := tun.doRead(buff, offset)
if err == nil || !rwcancel.ErrorIsEAGAIN(err) { if err == nil || !rwcancel.RetryAfterError(err) {
return n, err return n, err
} }
if !tun.rwcancel.ReadyRead() { if !tun.rwcancel.ReadyRead() {

View file

@ -6,14 +6,15 @@
package tun package tun
import ( import (
"git.zx2c4.com/wireguard-go/rwcancel"
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"git.zx2c4.com/wireguard-go/rwcancel"
"golang.org/x/net/ipv6" "golang.org/x/net/ipv6"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"net" "net"
"os" "os"
"syscall"
"unsafe" "unsafe"
) )
@ -67,8 +68,12 @@ func (tun *nativeTun) routineRouteListener(tunIfindex int) {
data := make([]byte, os.Getpagesize()) data := make([]byte, os.Getpagesize())
for { for {
retry:
n, err := unix.Read(tun.routeSocket, data) n, err := unix.Read(tun.routeSocket, data)
if err != nil { if err != nil {
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINTR {
goto retry
}
tun.errors <- err tun.errors <- err
return return
} }
@ -392,7 +397,7 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { func (tun *nativeTun) Read(buff []byte, offset int) (int, error) {
for { for {
n, err := tun.doRead(buff, offset) n, err := tun.doRead(buff, offset)
if err == nil || !rwcancel.ErrorIsEAGAIN(err) { if err == nil || !rwcancel.RetryAfterError(err) {
return n, err return n, err
} }
if !tun.rwcancel.ReadyRead() { if !tun.rwcancel.ReadyRead() {

View file

@ -12,10 +12,10 @@ package tun
*/ */
import ( import (
"git.zx2c4.com/wireguard-go/rwcancel"
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"git.zx2c4.com/wireguard-go/rwcancel"
"golang.org/x/net/ipv6" "golang.org/x/net/ipv6"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"net" "net"
@ -102,7 +102,7 @@ func (tun *nativeTun) routineNetlinkListener() {
var msgn int var msgn int
for { for {
msgn, _, _, _, err = unix.Recvmsg(tun.netlinkSock, msg[:], nil, 0) msgn, _, _, _, err = unix.Recvmsg(tun.netlinkSock, msg[:], nil, 0)
if err == nil || !rwcancel.ErrorIsEAGAIN(err) { if err == nil || !rwcancel.RetryAfterError(err) {
break break
} }
if !tun.netlinkCancel.ReadyRead() { if !tun.netlinkCancel.ReadyRead() {
@ -334,7 +334,7 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { func (tun *nativeTun) Read(buff []byte, offset int) (int, error) {
for { for {
n, err := tun.doRead(buff, offset) n, err := tun.doRead(buff, offset)
if err == nil || !rwcancel.ErrorIsEAGAIN(err) { if err == nil || !rwcancel.RetryAfterError(err) {
return n, err return n, err
} }
if !tun.fdCancel.ReadyRead() { if !tun.fdCancel.ReadyRead() {

View file

@ -6,9 +6,9 @@
package tun package tun
import ( import (
"git.zx2c4.com/wireguard-go/rwcancel"
"errors" "errors"
"fmt" "fmt"
"git.zx2c4.com/wireguard-go/rwcancel"
"golang.org/x/net/ipv6" "golang.org/x/net/ipv6"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"io/ioutil" "io/ioutil"
@ -46,8 +46,12 @@ func (tun *nativeTun) routineRouteListener(tunIfindex int) {
data := make([]byte, os.Getpagesize()) data := make([]byte, os.Getpagesize())
for { for {
retry:
n, err := unix.Read(tun.routeSocket, data) n, err := unix.Read(tun.routeSocket, data)
if err != nil { if err != nil {
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINTR {
goto retry
}
tun.errors <- err tun.errors <- err
return return
} }
@ -90,9 +94,7 @@ func (tun *nativeTun) routineRouteListener(tunIfindex int) {
func errorIsEBUSY(err error) bool { func errorIsEBUSY(err error) bool {
if pe, ok := err.(*os.PathError); ok { if pe, ok := err.(*os.PathError); ok {
if errno, ok := pe.Err.(syscall.Errno); ok && errno == syscall.EBUSY { err = pe.Err
return true
}
} }
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EBUSY { if errno, ok := err.(syscall.Errno); ok && errno == syscall.EBUSY {
return true return true
@ -237,7 +239,7 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
func (tun *nativeTun) Read(buff []byte, offset int) (int, error) { func (tun *nativeTun) Read(buff []byte, offset int) (int, error) {
for { for {
n, err := tun.doRead(buff, offset) n, err := tun.doRead(buff, offset)
if err == nil || !rwcancel.ErrorIsEAGAIN(err) { if err == nil || !rwcancel.RetryAfterError(err) {
return n, err return n, err
} }
if !tun.rwcancel.ReadyRead() { if !tun.rwcancel.ReadyRead() {

View file

@ -7,9 +7,9 @@
package main package main
import ( import (
"git.zx2c4.com/wireguard-go/rwcancel"
"errors" "errors"
"fmt" "fmt"
"git.zx2c4.com/wireguard-go/rwcancel"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"net" "net"
"os" "os"