mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-11-04 01:17:02 +00:00
On Windows, os.Rename (MoveFileEx) opens the file with DELETE access, renames it, then closes that handle. For a moment the new name is already listed while the handle is still open, and os.ReadFile, which shares only reading and writing, fails with ERROR_SHARING_VIOLATION. The WAL reader lists a segment as soon as Put renames it into place, and any Get error other than "not found" ends the stream: xdrive_test.go:143: ReadFull: transport/internet/xdrive: failed to read streams/<id>/c2s/000000001.seg > open ...\000000001.seg: The process cannot access the file because it is being used by another process. Measured on Windows 11 (Defender real-time protection on, 22 logical CPUs) with a reader that keeps opening the new name during the rename: 98.6% of 5,001 renames hit the error, every failed open started before MoveFileEx returned, and none failed with FILE_SHARE_DELETE added to the open. The window is about 0.3 ms when idle, but 10 ms median and up to 124 ms with all CPUs busy, which is why it shows up in full `go test ./...` runs. Under such load (22 busy-loop processes) the unfixed TestMultiSegmentTransfer, TestRoundTrip, TestInterleaved and TestCloseEOF failed 4 of 60 runs; with this change, 0 of 120. Get now retries os.ReadFile on ERROR_SHARING_VIOLATION for up to 2 seconds, as cmd/internal/robustio does, backing off from 1 ms to 100 ms and returning early once ctx is done. Other platforms still call os.ReadFile once. TestLocalSharingViolation holds a segment open with DELETE access, as MoveFileEx does, and checks that Get waits for it. Opening with FILE_SHARE_DELETE would avoid the conflict, but os.Open cannot set the share mode, and a raw CreateFile would lose its long path handling. Put's rename is unchanged: no rename failed in about 63,000 renames during these measurements, idle or under load. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>