]> Cypherpunks repositories - gostls13.git/commitdiff
internal/poll,net: set SIO_UDP_CONNRESET in net
authorqmuntal <quimmuntal@gmail.com>
Tue, 25 Mar 2025 09:29:22 +0000 (10:29 +0100)
committerGopher Robot <gobot@golang.org>
Tue, 25 Mar 2025 18:36:25 +0000 (11:36 -0700)
Setting the SIO_UDP_CONNRESET option in internal/poll.FD.Init
adds unnecessary complexity to the FD.Init signature and
implementation. Better to set it in the net package when initializing
the UDP connection, which is where conceptually it belongs.

While here, update an outdated comment in FD.Init that said the runtime
poller doesn't support I/O operations initialized by the user
outside the internal/poll package. It does support those operations
since CL 561895.

For #19098.
Updates #21172.

Change-Id: I9a70b0deafdb4619830abe2147e2d366b4c2b890
Reviewed-on: https://go-review.googlesource.com/c/go/+/660496
Auto-Submit: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
src/internal/poll/fd_windows.go
src/internal/poll/fd_windows_test.go
src/net/fd_windows.go

index 958edfbc0cf641218f3d5fc4b237a9537a388e2f..3c11ce5bb4444265e8b69ca238926ba6caef7cae 100644 (file)
@@ -281,9 +281,9 @@ var logInitFD func(net string, fd *FD, err error)
 // The net argument is a network name from the net package (e.g., "tcp"),
 // or "file" or "console" or "dir".
 // Set pollable to true if fd should be managed by runtime netpoll.
-func (fd *FD) Init(net string, pollable bool) (string, error) {
+func (fd *FD) Init(net string, pollable bool) error {
        if initErr != nil {
-               return "", initErr
+               return initErr
        }
 
        switch net {
@@ -299,32 +299,27 @@ func (fd *FD) Init(net string, pollable bool) (string, error) {
                "unix", "unixgram", "unixpacket":
                fd.kind = kindNet
        default:
-               return "", errors.New("internal error: unknown network type " + net)
+               return errors.New("internal error: unknown network type " + net)
        }
        fd.isFile = fd.kind != kindNet
 
        var err error
        if pollable {
-               // Only call init for a network socket.
-               // This means that we don't add files to the runtime poller.
-               // Adding files to the runtime poller can confuse matters
-               // if the user is doing their own overlapped I/O.
-               // See issue #21172.
+               // Note that the runtime poller will ignore I/O completion
+               // notifications not initiated by this package,
+               // so it is safe to add handles owned by the caller.
                //
-               // In general the code below avoids calling the execIO
-               // function for non-network sockets. If some method does
-               // somehow call execIO, then execIO, and therefore the
-               // calling method, will return an error, because
-               // fd.pd.runtimeCtx will be 0.
+               // If we could not add the handle to the runtime poller,
+               // assume the handle hasn't been opened for overlapped I/O.
                err = fd.pd.init(fd)
        }
        if logInitFD != nil {
                logInitFD(net, fd, err)
        }
-       if err != nil {
-               return "", err
+       if !pollable || err != nil {
+               return err
        }
-       if pollable && (fd.kind != kindNet || socketCanUseSetFileCompletionNotificationModes) {
+       if fd.kind != kindNet || socketCanUseSetFileCompletionNotificationModes {
                // Non-socket handles can use SetFileCompletionNotificationModes without problems.
                err := syscall.SetFileCompletionNotificationModes(fd.Sysfd,
                        syscall.FILE_SKIP_SET_EVENT_ON_HANDLE|syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS,
@@ -333,25 +328,13 @@ func (fd *FD) Init(net string, pollable bool) (string, error) {
                        fd.skipSyncNotif = true
                }
        }
-       // Disable SIO_UDP_CONNRESET behavior.
-       // http://support.microsoft.com/kb/263823
-       switch net {
-       case "udp", "udp4", "udp6":
-               ret := uint32(0)
-               flag := uint32(0)
-               size := uint32(unsafe.Sizeof(flag))
-               err := syscall.WSAIoctl(fd.Sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
-               if err != nil {
-                       return "wsaioctl", err
-               }
-       }
        fd.rop.mode = 'r'
        fd.wop.mode = 'w'
        fd.rop.fd = fd
        fd.wop.fd = fd
        fd.rop.runtimeCtx = fd.pd.runtimeCtx
        fd.wop.runtimeCtx = fd.pd.runtimeCtx
-       return "", nil
+       return nil
 }
 
 func (fd *FD) destroy() error {
index 8bf92be7c32b91a257af2bc596277e35a4e618f6..87273c08acce85ec62b43ce9b0fd87ed9fa9bb1b 100644 (file)
@@ -121,8 +121,7 @@ func TestWSASocketConflict(t *testing.T) {
                t.Fatal(err)
        }
        fd := poll.FD{Sysfd: s, IsStream: true, ZeroReadIsEOF: true}
-       _, err = fd.Init("tcp", true)
-       if err != nil {
+       if err = fd.Init("tcp", true); err != nil {
                syscall.CloseHandle(s)
                t.Fatal(err)
        }
index 5d7a1d54c31a32f3f4d023c71c550a71c93e36f8..f7609a7cfe8c2879a41725c8101bbb92ed55b2ca 100644 (file)
@@ -53,11 +53,22 @@ func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error)
 }
 
 func (fd *netFD) init() error {
-       errcall, err := fd.pfd.Init(fd.net, true)
-       if errcall != "" {
-               err = wrapSyscallError(errcall, err)
+       if err := fd.pfd.Init(fd.net, true); err != nil {
+               return err
        }
-       return err
+       switch fd.net {
+       case "udp", "udp4", "udp6":
+               // Disable reporting of PORT_UNREACHABLE errors.
+               // See https://go.dev/issue/5834.
+               ret := uint32(0)
+               flag := uint32(0)
+               size := uint32(unsafe.Sizeof(flag))
+               err := syscall.WSAIoctl(fd.pfd.Sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0)
+               if err != nil {
+                       return wrapSyscallError("wsaioctl", err)
+               }
+       }
+       return nil
 }
 
 // Always returns nil for connected peer address result.