Source file src/net/file_unix_test.go

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build unix
     6  
     7  package net
     8  
     9  import (
    10  	"internal/syscall/unix"
    11  	"testing"
    12  )
    13  
    14  // For backward compatibility, opening a net.Conn, turning it into an os.File,
    15  // and calling the Fd method should return a blocking descriptor.
    16  func TestFileFdBlocks(t *testing.T) {
    17  	if !testableNetwork("unix") {
    18  		t.Skipf("skipping: unix sockets not supported")
    19  	}
    20  
    21  	ls := newLocalServer(t, "unix")
    22  	defer ls.teardown()
    23  
    24  	errc := make(chan error, 1)
    25  	done := make(chan bool)
    26  	handler := func(ls *localServer, ln Listener) {
    27  		server, err := ln.Accept()
    28  		errc <- err
    29  		if err != nil {
    30  			return
    31  		}
    32  		defer server.Close()
    33  		<-done
    34  	}
    35  	if err := ls.buildup(handler); err != nil {
    36  		t.Fatal(err)
    37  	}
    38  	defer close(done)
    39  
    40  	client, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
    41  	if err != nil {
    42  		t.Fatal(err)
    43  	}
    44  	defer client.Close()
    45  
    46  	if err := <-errc; err != nil {
    47  		t.Fatalf("server error: %v", err)
    48  	}
    49  
    50  	// The socket should be non-blocking.
    51  	rawconn, err := client.(*UnixConn).SyscallConn()
    52  	if err != nil {
    53  		t.Fatal(err)
    54  	}
    55  	err = rawconn.Control(func(fd uintptr) {
    56  		nonblock, err := unix.IsNonblock(int(fd))
    57  		if err != nil {
    58  			t.Fatal(err)
    59  		}
    60  		if !nonblock {
    61  			t.Fatal("unix socket is in blocking mode")
    62  		}
    63  	})
    64  	if err != nil {
    65  		t.Fatal(err)
    66  	}
    67  
    68  	file, err := client.(*UnixConn).File()
    69  	if err != nil {
    70  		t.Fatal(err)
    71  	}
    72  
    73  	// At this point the descriptor should still be non-blocking.
    74  	rawconn, err = file.SyscallConn()
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  	err = rawconn.Control(func(fd uintptr) {
    79  		nonblock, err := unix.IsNonblock(int(fd))
    80  		if err != nil {
    81  			t.Fatal(err)
    82  		}
    83  		if !nonblock {
    84  			t.Fatal("unix socket as os.File is in blocking mode")
    85  		}
    86  	})
    87  	if err != nil {
    88  		t.Fatal(err)
    89  	}
    90  
    91  	fd := file.Fd()
    92  
    93  	// Calling Fd should have put the descriptor into blocking mode.
    94  	nonblock, err := unix.IsNonblock(int(fd))
    95  	if err != nil {
    96  		t.Fatal(err)
    97  	}
    98  	if nonblock {
    99  		t.Error("unix socket through os.File.Fd is non-blocking")
   100  	}
   101  }
   102  

View as plain text