diff options
author | Simon Rozman <simon@rozman.si> | 2019-04-04 09:19:35 +0200 |
---|---|---|
committer | Simon Rozman <simon@rozman.si> | 2019-04-04 09:20:18 +0200 |
commit | 767c86f8cb9388486fbcde8b0aa66a2b10cf3e2b (patch) | |
tree | 39a17d62be76e64c14e1bddf3ba561ad0dbf1e90 /tun | |
parent | 421c1f9143347d279c5a296a302720754b2a21b2 (diff) |
tun: windows: Retry R/W on ERROR_OPERATION_ABORTED
Signed-off-by: Simon Rozman <simon@rozman.si>
Diffstat (limited to 'tun')
-rw-r--r-- | tun/tun_windows.go | 62 |
1 files changed, 44 insertions, 18 deletions
diff --git a/tun/tun_windows.go b/tun/tun_windows.go index 4d26dce..386b518 100644 --- a/tun/tun_windows.go +++ b/tun/tun_windows.go @@ -9,6 +9,7 @@ import ( "errors" "os" "sync" + "syscall" "time" "unsafe" @@ -119,7 +120,7 @@ func (tun *NativeTun) openTUN() error { for tun.tunFileWrite == nil { tun.tunFileWrite, err = os.OpenFile(name, os.O_WRONLY, 0) if err != nil { - if retries > 0 { + if retries > 0 && !tun.close { time.Sleep(time.Second / retryRate) retries-- continue @@ -258,18 +259,31 @@ func (tun *NativeTun) Read(buff []byte, offset int) (int, error) { } // Fill queue. - n, err := file.Read(tun.rdBuff.data[:]) - if err != nil { - tun.rdBuff.offset = 0 - tun.rdBuff.avail = 0 - if tun.close { + retries := retryTimeout * retryRate + for { + n, err := file.Read(tun.rdBuff.data[:]) + if err != nil { + 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 } - tun.closeTUN() - continue + tun.rdBuff.offset = 0 + 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. - _, err = file.Write(tun.wrBuff.data[:tun.wrBuff.offset]) - tun.wrBuff.packetNum = 0 - tun.wrBuff.offset = 0 - if err != nil { - if tun.close { + retries := retryTimeout * retryRate + for { + _, err = file.Write(tun.wrBuff.data[:tun.wrBuff.offset]) + tun.wrBuff.packetNum = 0 + 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 } - tun.closeTUN() - continue + return nil } - return nil } } |