Catch EINTR
This commit is contained in:
parent
66f6ca3e4a
commit
2f2eca8947
|
@ -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() {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
)
|
)
|
||||||
|
|
2
main.go
2
main.go
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in a new issue