]> git.ipfire.org Git - thirdparty/wireguard-go.git/commitdiff
tun: windows: Retry R/W on ERROR_OPERATION_ABORTED
authorSimon Rozman <simon@rozman.si>
Thu, 4 Apr 2019 07:19:35 +0000 (09:19 +0200)
committerSimon Rozman <simon@rozman.si>
Thu, 4 Apr 2019 07:20:18 +0000 (09:20 +0200)
Signed-off-by: Simon Rozman <simon@rozman.si>
tun/tun_windows.go

index 4d26dcea6d0ed93175b389b050bfe6a844438640..386b5186b1ef6760347d3d34d431e8edd595a9b9 100644 (file)
@@ -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
        }
 }