authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-14 17:21:29-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-15 10:48:15-07:00
log6d6f6a4ac6f1f2666fa2d4500ef4634fdfe0d947
tree3bd6fa9ddb21fd74572feb5c771f2617defb1ebb
parent717e2c8718a3161d6b86317b6132fa296325a88c

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.

1 files changed, 47 insertions(+), 35 deletions(-)

lib/std/os/windows.zig+47-35
......@@ -105,41 +105,53 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
105105 // If we're not following symlinks, we need to ensure we don't pass in any synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT.
106106 const flags: ULONG = if (options.follow_symlinks) file_or_dir_flag | blocking_flag else file_or_dir_flag | FILE_OPEN_REPARSE_POINT;
107107
108 const rc = ntdll.NtCreateFile(
109 &result,
110 options.access_mask,
111 &attr,
112 &io,
113 null,
114 FILE_ATTRIBUTE_NORMAL,
115 options.share_access,
116 options.creation,
117 flags,
118 null,
119 0,
120 );
121 switch (rc) {
122 .SUCCESS => {
123 if (std.io.is_async and options.io_mode == .evented) {
124 _ = CreateIoCompletionPort(result, std.event.Loop.instance.?.os_data.io_port, undefined, undefined) catch undefined;
125 }
126 return result;
127 },
128 .OBJECT_NAME_INVALID => unreachable,
129 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
130 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
131 .NO_MEDIA_IN_DEVICE => return error.NoDevice,
132 .INVALID_PARAMETER => unreachable,
133 .SHARING_VIOLATION => return error.AccessDenied,
134 .ACCESS_DENIED => return error.AccessDenied,
135 .PIPE_BUSY => return error.PipeBusy,
136 .OBJECT_PATH_SYNTAX_BAD => unreachable,
137 .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
138 .FILE_IS_A_DIRECTORY => return error.IsDir,
139 .NOT_A_DIRECTORY => return error.NotDir,
140 .USER_MAPPED_FILE => return error.AccessDenied,
141 .INVALID_HANDLE => unreachable,
142 else => return unexpectedStatus(rc),
108 while (true) {
109 const rc = ntdll.NtCreateFile(
110 &result,
111 options.access_mask,
112 &attr,
113 &io,
114 null,
115 FILE_ATTRIBUTE_NORMAL,
116 options.share_access,
117 options.creation,
118 flags,
119 null,
120 0,
121 );
122 switch (rc) {
123 .SUCCESS => {
124 if (std.io.is_async and options.io_mode == .evented) {
125 _ = CreateIoCompletionPort(result, std.event.Loop.instance.?.os_data.io_port, undefined, undefined) catch undefined;
126 }
127 return result;
128 },
129 .OBJECT_NAME_INVALID => unreachable,
130 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
131 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
132 .NO_MEDIA_IN_DEVICE => return error.NoDevice,
133 .INVALID_PARAMETER => unreachable,
134 .SHARING_VIOLATION => return error.AccessDenied,
135 .ACCESS_DENIED => return error.AccessDenied,
136 .PIPE_BUSY => return error.PipeBusy,
137 .OBJECT_PATH_SYNTAX_BAD => unreachable,
138 .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
139 .FILE_IS_A_DIRECTORY => return error.IsDir,
140 .NOT_A_DIRECTORY => return error.NotDir,
141 .USER_MAPPED_FILE => return error.AccessDenied,
142 .INVALID_HANDLE => unreachable,
143 .DELETE_PENDING => {
144 // This error means that there *was* a file in this location on
145 // the file system, but it was deleted. However, the OS is not
146 // finished with the deletion operation, and so this CreateFile
147 // call has failed. There is not really a sane way to handle
148 // this other than retrying the creation after the OS finishes
149 // the deletion.
150 std.time.sleep(std.time.ns_per_ms);
151 continue;
152 },
153 else => return unexpectedStatus(rc),
154 }
143155 }
144156}
145157