authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-12-29 16:51:20-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 19:49:08-07:00
log6b2709616e22e7651f16293034cc0d25f0e9be0a
treed3dc659be126b3e6212197c955c52fbe277894a9
parenta89d6878d2780f966b7327f8d366e6ac5f5cd8fc

frontend: ignore AccessDenied when writing builtin.zig

This issue already existed in master branch, however, the more aggressive caching of builtin.zig in this branch made it happen more often. I added doc comments to AtomicFile to explain when this problem can occur. For the compiler's use case, error.AccessDenied can be simply swallowed because it means the destination file already exists and there is nothing else to do besides proceed with the AtomicFile cleanup. I never solved the mystery of why the log statements weren't printing but those are temporary debugging instruments anyway, and I am already too many yaks deep to whip out another razor. closes #14978

2 files changed, 17 insertions(+), 17 deletions(-)

lib/std/fs/AtomicFile.zig+4
...@@ -65,6 +65,10 @@ pub fn deinit(self: *AtomicFile) void {...@@ -65,6 +65,10 @@ pub fn deinit(self: *AtomicFile) void {
6565
66pub const FinishError = posix.RenameError;66pub const FinishError = posix.RenameError;
6767
68/// On Windows, this function introduces a period of time where some file
69/// system operations on the destination file will result in
70/// `error.AccessDenied`, including rename operations (such as the one used in
71/// this function).
68pub fn finish(self: *AtomicFile) FinishError!void {72pub fn finish(self: *AtomicFile) FinishError!void {
69 assert(self.file_exists);73 assert(self.file_exists);
70 if (self.file_open) {74 if (self.file_open) {
src/Builtin.zig+13-17
...@@ -280,24 +280,19 @@ pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void {...@@ -280,24 +280,19 @@ pub fn populateFile(comp: *Compilation, mod: *Module, file: *File) !void {
280280
281fn writeFile(file: *File, mod: *Module) !void {281fn writeFile(file: *File, mod: *Module) !void {
282 var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;282 var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
283 var af = mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }, &buf) catch |err| {283 var af = try mod.root.atomicFile(mod.root_src_path, .{ .make_path = true }, &buf);
284 std.log.warn("unable to create builtin atomic file '{}{s}'", .{
285 mod.root, mod.root_src_path,
286 });
287 return err;
288 };
289 defer af.deinit();284 defer af.deinit();
290 af.file.writeAll(file.source) catch |err| {285 try af.file.writeAll(file.source);
291 std.log.warn("unable to write builtin file data to '{}{s}'", .{286 af.finish() catch |err| switch (err) {
292 mod.root, mod.root_src_path,287 error.AccessDenied => switch (builtin.os.tag) {
293 });288 .windows => {
294 return err;289 // Very likely happened due to another process or thread
295 };290 // simultaneously creating the same, correct builtin.zig file.
296 af.finish() catch |err| {291 // This is not a problem; ignore it.
297 std.log.warn("unable to rename atomic builtin file into '{}{s}'", .{292 },
298 mod.root, mod.root_src_path,293 else => return err,
299 });294 },
300 return err;295 else => return err,
301 };296 };
302297
303 file.stat = .{298 file.stat = .{
...@@ -307,6 +302,7 @@ fn writeFile(file: *File, mod: *Module) !void {...@@ -307,6 +302,7 @@ fn writeFile(file: *File, mod: *Module) !void {
307 };302 };
308}303}
309304
305const builtin = @import("builtin");
310const std = @import("std");306const std = @import("std");
311const Allocator = std.mem.Allocator;307const Allocator = std.mem.Allocator;
312const build_options = @import("build_options");308const build_options = @import("build_options");