mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
internal/poll,net: set SIO_UDP_CONNRESET in net
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>
This commit is contained in:
parent
35c9864897
commit
936bb82ddb
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user