]> Cypherpunks.ru repositories - govpn.git/commitdiff
fix close by interrupt read, do not close multiple times
authorBruno Clermont <bruno@robotinfra.com>
Tue, 7 Mar 2017 03:48:52 +0000 (11:48 +0800)
committerBruno Clermont <bruno@robotinfra.com>
Tue, 7 Mar 2017 03:48:52 +0000 (11:48 +0800)
src/cypherpunks.ru/govpn/tap.go
src/cypherpunks.ru/govpn/tap_android.go

index efb53a3e591c95dacf1f90057a9d065a63292ac4..dd3c7e9dd678606997c88ec2991430988aff9f1f 100644 (file)
@@ -36,6 +36,7 @@ type TAP struct {
        Name string
        Sink chan []byte
        dev  io.ReadWriteCloser
+       closed bool
 }
 
 var (
@@ -70,6 +71,9 @@ func NewTAP(ifaceName string, mtu int) (*TAP, error) {
                        bufZ = !bufZ
                        n, err = tap.dev.Read(buf)
                        if err != nil {
+                               if tap.closed {
+                                       return
+                               }
                                logger.WithError(err).WithFields(logrus.Fields{
                                        "func": logFuncPrefix + "TAP read sink loop",
                                        "name": tap.Name,
@@ -93,8 +97,15 @@ func (t *TAP) Write(data []byte) (int, error) {
 
 // Close close TAP/TUN virtual network interface
 func (t *TAP) Close() error {
-       // TODO add chan to stop read loop
-       return t.dev.Close()
+       if t.closed {
+               return nil
+       }
+       err := t.dev.Close()
+       if err != nil {
+               return errors.Wrap(err, "water.Interface.Close")
+       }
+       t.closed = true
+       return nil
 }
 
 // TAPListen opens an existing TAP (creates if none exists)
index 15c5940f7648819eeffb8e1c6bdaee1123e182b2..1530d2e2cae2047e5f6fa011bfe72b2b0c5f61b4 100644 (file)
@@ -53,6 +53,10 @@ func TapListenFileDescriptor(fd uintptr, ifaceName string, mtu int) *TAP {
                        bufZ = !bufZ
                        n, err = tap.dev.Read(buf)
                        if err != nil {
+                               if tap.closed {
+                                       return
+                               }
+
                                e, ok := err.(*os.PathError)
                                if ok && e.Err == syscall.EAGAIN {
                                        time.Sleep(time.Millisecond * 20)