aboutsummaryrefslogtreecommitdiff
path: root/src/os/file_windows.go
diff options
context:
space:
mode:
authorAlan Donovan <adonovan@google.com>2024-04-12 16:08:22 -0400
committerAlan Donovan <adonovan@google.com>2024-04-15 20:52:06 +0000
commitca94e9e223888d6d99a8f7b559f08bb59d2cc5fd (patch)
treed03cbd7f16a89c0912f9e5278f4d05a2a0145520 /src/os/file_windows.go
parent7418d419afeeaa832bd5c9104f1ff90331eaf184 (diff)
downloadgo-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.go15
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)