Browse Source

Linux set interface underlying fd to non-blocking

LE Manh Cuong 6 years ago
parent
commit
4d58427608
2 changed files with 47 additions and 2 deletions
  1. 34 0
      ipv4_test.go
  2. 13 2
      syscalls_linux.go

+ 34 - 0
ipv4_test.go

@@ -1,6 +1,7 @@
 package water
 
 import (
+	"context"
 	"net"
 	"testing"
 	"time"
@@ -74,3 +75,36 @@ readFrame:
 		}
 	}
 }
+
+func TestCloseUnblockPendingRead(t *testing.T) {
+	var (
+		self = net.IPv4(192, 168, 150, 1)
+		mask = net.IPv4Mask(255, 255, 255, 0)
+	)
+
+	ifce, err := New(Config{DeviceType: TUN})
+	if err != nil {
+		t.Fatalf("creating TUN error: %v\n", err)
+	}
+
+	setupIfce(t, net.IPNet{IP: self, Mask: mask}, ifce.Name())
+	c := make(chan struct{})
+	go func() {
+		ifce.Read(make([]byte, 1<<16))
+		close(c)
+	}()
+
+	// make sure ifce.Close() happens after ifce.Read()
+	time.Sleep(1 * time.Second)
+
+	ifce.Close()
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+	defer cancel()
+
+	select {
+	case <-c:
+		t.Log("Pending Read unblocked")
+	case <-ctx.Done():
+		t.Fatal("Timeouted, pending read blocked")
+	}
+}

+ 13 - 2
syscalls_linux.go

@@ -31,7 +31,7 @@ func ioctl(fd uintptr, request uintptr, argp uintptr) error {
 }
 
 func newTAP(config Config) (ifce *Interface, err error) {
-	file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
+	file, err := openTun()
 	if err != nil {
 		return nil, err
 	}
@@ -55,7 +55,7 @@ func newTAP(config Config) (ifce *Interface, err error) {
 }
 
 func newTUN(config Config) (ifce *Interface, err error) {
-	file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
+	file, err := openTun()
 	if err != nil {
 		return nil, err
 	}
@@ -107,5 +107,16 @@ func setDeviceOptions(fd uintptr, config Config) (err error) {
 	if config.Persist {
 		value = 1
 	}
+
 	return ioctl(fd, syscall.TUNSETPERSIST, uintptr(value))
 }
+
+func openTun() (*os.File, error) {
+	tunFile := "/dev/net/tun"
+	bfile, err := os.OpenFile(tunFile, os.O_RDWR, 0)
+	if err != nil {
+		return nil, err
+	}
+
+	return os.NewFile(bfile.Fd(), tunFile), nil
+}