commit 6d6f6a4ac6f1f2666fa2d4500ef4634fdfe0d947 (tree)
parent 717e2c8718a3161d6b86317b6132fa296325a88c
Author: Andrew Kelley <andrew@ziglang.org>
Date: Tue, 14 Mar 2023 17:21:29 -0700
std.os.windows.OpenFile: handle DELETE_PENDING
This error means that there *was* a file in this location on the file
system, but it was deleted. However, the OS is not finished with the
deletion operation, and so this CreateFile call has failed. There is not
really a sane way to handle this other than retrying the creation after
the OS finishes the deletion.
Diffstat:
1 file changed, 47 insertions(+), 35 deletions(-)
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
@@ -105,41 +105,53 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
// If we're not following symlinks, we need to ensure we don't pass in any synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT.
const flags: ULONG = if (options.follow_symlinks) file_or_dir_flag | blocking_flag else file_or_dir_flag | FILE_OPEN_REPARSE_POINT;
- const rc = ntdll.NtCreateFile(
- &result,
- options.access_mask,
- &attr,
- &io,
- null,
- FILE_ATTRIBUTE_NORMAL,
- options.share_access,
- options.creation,
- flags,
- null,
- 0,
- );
- switch (rc) {
- .SUCCESS => {
- if (std.io.is_async and options.io_mode == .evented) {
- _ = CreateIoCompletionPort(result, std.event.Loop.instance.?.os_data.io_port, undefined, undefined) catch undefined;
- }
- return result;
- },
- .OBJECT_NAME_INVALID => unreachable,
- .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
- .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
- .NO_MEDIA_IN_DEVICE => return error.NoDevice,
- .INVALID_PARAMETER => unreachable,
- .SHARING_VIOLATION => return error.AccessDenied,
- .ACCESS_DENIED => return error.AccessDenied,
- .PIPE_BUSY => return error.PipeBusy,
- .OBJECT_PATH_SYNTAX_BAD => unreachable,
- .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
- .FILE_IS_A_DIRECTORY => return error.IsDir,
- .NOT_A_DIRECTORY => return error.NotDir,
- .USER_MAPPED_FILE => return error.AccessDenied,
- .INVALID_HANDLE => unreachable,
- else => return unexpectedStatus(rc),
+ while (true) {
+ const rc = ntdll.NtCreateFile(
+ &result,
+ options.access_mask,
+ &attr,
+ &io,
+ null,
+ FILE_ATTRIBUTE_NORMAL,
+ options.share_access,
+ options.creation,
+ flags,
+ null,
+ 0,
+ );
+ switch (rc) {
+ .SUCCESS => {
+ if (std.io.is_async and options.io_mode == .evented) {
+ _ = CreateIoCompletionPort(result, std.event.Loop.instance.?.os_data.io_port, undefined, undefined) catch undefined;
+ }
+ return result;
+ },
+ .OBJECT_NAME_INVALID => unreachable,
+ .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
+ .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
+ .NO_MEDIA_IN_DEVICE => return error.NoDevice,
+ .INVALID_PARAMETER => unreachable,
+ .SHARING_VIOLATION => return error.AccessDenied,
+ .ACCESS_DENIED => return error.AccessDenied,
+ .PIPE_BUSY => return error.PipeBusy,
+ .OBJECT_PATH_SYNTAX_BAD => unreachable,
+ .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
+ .FILE_IS_A_DIRECTORY => return error.IsDir,
+ .NOT_A_DIRECTORY => return error.NotDir,
+ .USER_MAPPED_FILE => return error.AccessDenied,
+ .INVALID_HANDLE => unreachable,
+ .DELETE_PENDING => {
+ // This error means that there *was* a file in this location on
+ // the file system, but it was deleted. However, the OS is not
+ // finished with the deletion operation, and so this CreateFile
+ // call has failed. There is not really a sane way to handle
+ // this other than retrying the creation after the OS finishes
+ // the deletion.
+ std.time.sleep(std.time.ns_per_ms);
+ continue;
+ },
+ else => return unexpectedStatus(rc),
+ }
}
}