tun: windows: Retry R/W on ERROR_OPERATION_ABORTED

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2019-04-04 09:19:35 +02:00
parent 421c1f9143
commit 767c86f8cb

View file

@ -9,6 +9,7 @@ import (
"errors" "errors"
"os" "os"
"sync" "sync"
"syscall"
"time" "time"
"unsafe" "unsafe"
@ -119,7 +120,7 @@ func (tun *NativeTun) openTUN() error {
for tun.tunFileWrite == nil { for tun.tunFileWrite == nil {
tun.tunFileWrite, err = os.OpenFile(name, os.O_WRONLY, 0) tun.tunFileWrite, err = os.OpenFile(name, os.O_WRONLY, 0)
if err != nil { if err != nil {
if retries > 0 { if retries > 0 && !tun.close {
time.Sleep(time.Second / retryRate) time.Sleep(time.Second / retryRate)
retries-- retries--
continue continue
@ -258,18 +259,31 @@ func (tun *NativeTun) Read(buff []byte, offset int) (int, error) {
} }
// Fill queue. // Fill queue.
retries := retryTimeout * retryRate
for {
n, err := file.Read(tun.rdBuff.data[:]) n, err := file.Read(tun.rdBuff.data[:])
if err != nil { if err != nil {
tun.rdBuff.offset = 0 tun.rdBuff.offset = 0
tun.rdBuff.avail = 0 tun.rdBuff.avail = 0
pe, ok := err.(*os.PathError)
if tun.close { if tun.close {
return 0, err return 0, os.ErrClosed
} }
tun.closeTUN() if retries > 0 && ok && pe.Err == windows.ERROR_OPERATION_ABORTED {
time.Sleep(time.Second / retryRate)
retries--
continue continue
} }
if ok && pe.Err == syscall.Errno(6) /*windows.ERROR_INVALID_HANDLE*/ {
tun.closeTUN()
break
}
return 0, err
}
tun.rdBuff.offset = 0 tun.rdBuff.offset = 0
tun.rdBuff.avail = uint32(n) tun.rdBuff.avail = uint32(n)
break
}
} }
} }
@ -288,19 +302,31 @@ func (tun *NativeTun) Flush() error {
} }
// Flush write buffer. // Flush write buffer.
retries := retryTimeout * retryRate
for {
_, err = file.Write(tun.wrBuff.data[:tun.wrBuff.offset]) _, err = file.Write(tun.wrBuff.data[:tun.wrBuff.offset])
tun.wrBuff.packetNum = 0 tun.wrBuff.packetNum = 0
tun.wrBuff.offset = 0 tun.wrBuff.offset = 0
if err != nil { if err != nil {
pe, ok := err.(*os.PathError)
if tun.close { if tun.close {
return err return os.ErrClosed
} }
tun.closeTUN() if retries > 0 && ok && pe.Err == windows.ERROR_OPERATION_ABORTED {
time.Sleep(time.Second / retryRate)
retries--
continue continue
} }
if ok && pe.Err == syscall.Errno(6) /*windows.ERROR_INVALID_HANDLE*/ {
tun.closeTUN()
break
}
return err
}
return nil return nil
} }
} }
}
func (tun *NativeTun) putTunPacket(buff []byte) error { func (tun *NativeTun) putTunPacket(buff []byte) error {
size := uint32(len(buff)) size := uint32(len(buff))