mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
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 <dmitshur@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
parent
7007dfcd0c
commit
cac276f81a
@ -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)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user