From: qmuntal Date: Tue, 8 Apr 2025 13:31:02 +0000 (+0200) Subject: internal/poll: fix race in Close X-Git-Tag: go1.25rc1~509 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=cac276f81a5ff11ae3c9027c45d14469f2b7fb70;p=gostls13.git internal/poll: fix race in Close There is a potential race between a concurrent call to FD.initIO, which calls FD.pd.init, and a call to FD.Close, which calls FD.pd.evict. This is solved by calling FD.initIO in FD.Close, as that will block until the concurrent FD.initIO has completed. Note that FD.initIO is no-op if first called from here. The race window is so small that it is not possible to write a test that triggers it. Change-Id: Ie2f2818e746b9d626fe3b9eb6b8ff967c81ef863 Reviewed-on: https://go-review.googlesource.com/c/go/+/663815 Reviewed-by: Dmitri Shuralyov LUCI-TryBot-Result: Go LUCI Reviewed-by: Damien Neil --- diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 6660bcd959..99891de763 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -336,6 +336,10 @@ func (fd *FD) initIO() error { return nil } fd.initIOOnce.Do(func() { + if fd.closing() { + // Closing, nothing to do. + return + } // 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. @@ -434,6 +438,12 @@ func (fd *FD) Close() error { if !fd.fdmu.increfAndClose() { return errClosing(fd.isFile) } + // There is a potential race between a concurrent call to fd.initIO, + // which calls fd.pd.init, and the call to fd.pd.evict below. + // This is solved by calling fd.initIO ourselves, which will + // block until the concurrent fd.initIO has completed. Note + // that fd.initIO is no-op if first called from here. + fd.initIO() if fd.kind == kindPipe { syscall.CancelIoEx(fd.Sysfd, nil) }