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.
n, err := file.Read(tun.rdBuff.data[:]) retries := retryTimeout * retryRate
if err != nil { for {
tun.rdBuff.offset = 0 n, err := file.Read(tun.rdBuff.data[:])
tun.rdBuff.avail = 0 if err != nil {
if tun.close { tun.rdBuff.offset = 0
tun.rdBuff.avail = 0
pe, ok := err.(*os.PathError)
if tun.close {
return 0, os.ErrClosed
}
if retries > 0 && ok && pe.Err == windows.ERROR_OPERATION_ABORTED {
time.Sleep(time.Second / retryRate)
retries--
continue
}
if ok && pe.Err == syscall.Errno(6) /*windows.ERROR_INVALID_HANDLE*/ {
tun.closeTUN()
break
}
return 0, err return 0, err
} }
tun.closeTUN() tun.rdBuff.offset = 0
continue tun.rdBuff.avail = uint32(n)
break
} }
tun.rdBuff.offset = 0
tun.rdBuff.avail = uint32(n)
} }
} }
@ -288,17 +302,29 @@ func (tun *NativeTun) Flush() error {
} }
// Flush write buffer. // Flush write buffer.
_, err = file.Write(tun.wrBuff.data[:tun.wrBuff.offset]) retries := retryTimeout * retryRate
tun.wrBuff.packetNum = 0 for {
tun.wrBuff.offset = 0 _, err = file.Write(tun.wrBuff.data[:tun.wrBuff.offset])
if err != nil { tun.wrBuff.packetNum = 0
if tun.close { tun.wrBuff.offset = 0
if err != nil {
pe, ok := err.(*os.PathError)
if tun.close {
return os.ErrClosed
}
if retries > 0 && ok && pe.Err == windows.ERROR_OPERATION_ABORTED {
time.Sleep(time.Second / retryRate)
retries--
continue
}
if ok && pe.Err == syscall.Errno(6) /*windows.ERROR_INVALID_HANDLE*/ {
tun.closeTUN()
break
}
return err return err
} }
tun.closeTUN() return nil
continue
} }
return nil
} }
} }