diff options
| author | Alan Donovan <adonovan@google.com> | 2024-04-12 16:08:22 -0400 |
|---|---|---|
| committer | Alan Donovan <adonovan@google.com> | 2024-04-15 20:52:06 +0000 |
| commit | ca94e9e223888d6d99a8f7b559f08bb59d2cc5fd (patch) | |
| tree | d03cbd7f16a89c0912f9e5278f4d05a2a0145520 /src/os/file_windows.go | |
| parent | 7418d419afeeaa832bd5c9104f1ff90331eaf184 (diff) | |
| download | go-ca94e9e223888d6d99a8f7b559f08bb59d2cc5fd.tar.xz | |
os: make File.Readdir et al concurrency-safe
Before, all methods of File (including Close) were
safe for concurrent use (I checked), except the three
variants of ReadDir.
This change makes the ReadDir operations
atomic too, and documents explicitly that all methods
of File have this property, which was already implied
by the package documentation.
Fixes #66498
Change-Id: I05c88b4e60b44c702062e99ed8f4a32e7945927a
Reviewed-on: https://go-review.googlesource.com/c/go/+/578322
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/os/file_windows.go')
| -rw-r--r-- | src/os/file_windows.go | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/src/os/file_windows.go b/src/os/file_windows.go index 6ee15eb993..d883eb5cb2 100644 --- a/src/os/file_windows.go +++ b/src/os/file_windows.go @@ -11,6 +11,7 @@ import ( "internal/syscall/windows" "runtime" "sync" + "sync/atomic" "syscall" "unsafe" ) @@ -25,8 +26,8 @@ const _UTIME_OMIT = -1 type file struct { pfd poll.FD name string - dirinfo *dirInfo // nil unless directory being read - appendMode bool // whether file is opened for appending + dirinfo atomic.Pointer[dirInfo] // nil unless directory being read + appendMode bool // whether file is opened for appending } // Fd returns the Windows handle referencing the open file. @@ -127,9 +128,8 @@ func (file *file) close() error { if file == nil { return syscall.EINVAL } - if file.dirinfo != nil { - file.dirinfo.close() - file.dirinfo = nil + if info := file.dirinfo.Swap(nil); info != nil { + info.close() } var err error if e := file.pfd.Close(); e != nil { @@ -149,11 +149,10 @@ func (file *file) close() error { // relative to the current offset, and 2 means relative to the end. // It returns the new offset and an error, if any. func (f *File) seek(offset int64, whence int) (ret int64, err error) { - if f.dirinfo != nil { + if info := f.dirinfo.Swap(nil); info != nil { // Free cached dirinfo, so we allocate a new one if we // access this file as a directory again. See #35767 and #37161. - f.dirinfo.close() - f.dirinfo = nil + info.close() } ret, err = f.pfd.Seek(offset, whence) runtime.KeepAlive(f) |
