fix(windows): serialize private root contention

This commit is contained in:
2026-08-18 14:49:56 +02:00
parent feee4ee648
commit b261dd4d3a
@@ -82,7 +82,7 @@ func openWindowsPrivateDirectoryAt(parent windows.Handle, name string, ensure bo
return 0, false, ErrUnsafeFile return 0, false, ErrUnsafeFile
} }
for attempt := 0; attempt < 2; attempt++ { for attempt := 0; attempt < 2; attempt++ {
handle, err := openWindowsRelativeDirectory(parent, name) handle, err := openWindowsRelativePrivateDirectoryWithRetry(parent, name)
if err == nil { if err == nil {
return handle, true, nil return handle, true, nil
} }
@@ -100,6 +100,19 @@ func openWindowsPrivateDirectoryAt(parent windows.Handle, name string, ensure bo
return 0, false, ErrUnsafeFile return 0, false, ErrUnsafeFile
} }
func openWindowsRelativePrivateDirectoryWithRetry(parent windows.Handle, name string) (windows.Handle, error) {
for attempt := 0; ; attempt++ {
handle, err := openWindowsRelativeDirectory(parent, name)
if !isWindowsRelativeSharingViolation(err) {
return handle, err
}
if attempt == windowsPrivateSharingRetries {
return 0, err
}
time.Sleep(time.Millisecond)
}
}
func openWindowsRelativeDirectory(parent windows.Handle, name string) (windows.Handle, error) { func openWindowsRelativeDirectory(parent windows.Handle, name string) (windows.Handle, error) {
handle, err := openWindowsRelativeObject( handle, err := openWindowsRelativeObject(
parent, parent,
@@ -280,6 +293,11 @@ func isWindowsRelativeCollision(err error) bool {
errors.Is(err, windows.STATUS_OBJECT_NAME_COLLISION) errors.Is(err, windows.STATUS_OBJECT_NAME_COLLISION)
} }
func isWindowsRelativeSharingViolation(err error) bool {
return errors.Is(err, windows.ERROR_SHARING_VIOLATION) ||
errors.Is(err, windows.STATUS_SHARING_VIOLATION)
}
func (directory *windowsPrivateDirectory) captureAndValidate() error { func (directory *windowsPrivateDirectory) captureAndValidate() error {
if directory == nil || directory.handle == 0 { if directory == nil || directory.handle == 0 {
return ErrUnsafeFile return ErrUnsafeFile
@@ -953,7 +971,7 @@ func windowsRelativeClaimAbsentOrOrphan(directory *windowsPrivateDirectory, sour
return false, ErrUnsafeFile return false, ErrUnsafeFile
} }
const windowsClaimSharingRetries = 100 const windowsPrivateSharingRetries = 100
func waitForWindowsRelativeClaimLoss(directory *windowsPrivateDirectory, source, claim string) (bool, error) { func waitForWindowsRelativeClaimLoss(directory *windowsPrivateDirectory, source, claim string) (bool, error) {
for attempt := 0; ; attempt++ { for attempt := 0; ; attempt++ {
@@ -965,7 +983,7 @@ func waitForWindowsRelativeClaimLoss(directory *windowsPrivateDirectory, source,
if absentErr == nil && absent { if absentErr == nil && absent {
return true, nil return true, nil
} }
if attempt == windowsClaimSharingRetries { if attempt == windowsPrivateSharingRetries {
return false, ErrUnsafeFile return false, ErrUnsafeFile
} }
time.Sleep(time.Millisecond) time.Sleep(time.Millisecond)
@@ -980,11 +998,10 @@ func openWindowsPrivateClaimRegular(
) (*windowsPrivateRegularAt, error) { ) (*windowsPrivateRegularAt, error) {
for attempt := 0; ; attempt++ { for attempt := 0; ; attempt++ {
value, err := openWindowsPrivateRegularAt(directory, name, access, allowedLinks) value, err := openWindowsPrivateRegularAt(directory, name, access, allowedLinks)
if !errors.Is(err, windows.ERROR_SHARING_VIOLATION) && if !isWindowsRelativeSharingViolation(err) {
!errors.Is(err, windows.STATUS_SHARING_VIOLATION) {
return value, err return value, err
} }
if attempt == windowsClaimSharingRetries { if attempt == windowsPrivateSharingRetries {
return nil, err return nil, err
} }
time.Sleep(time.Millisecond) time.Sleep(time.Millisecond)