Surprising behaviour while working with the filesystem

Hello,

I don’t think this is particular about Zig, but I have found a quite peculiar behaviour of the following program on at least my system (Fedora 41):

const std = @import("std");

const name = "testfile";

pub fn main() !void {
    var original = try std.fs.cwd().createFile(name, .{.read = true});
    defer {
        std.fs.cwd().deleteFile(name) catch |err| std.debug.print("delete failed: {}\n", .{err});
        original.close();
    }

    const pid = try std.posix.fork();
    if (pid != 0) {
        std.debug.print("child exited with: {}\n", .{std.posix.waitpid(pid, 0).status});
        var buf = [_]u8{0} ** 50;
        const amount = try original.readAll(&buf);
        std.debug.print("{s}\n", .{buf[0..amount]});
        _ = std.io.getStdIn().reader().readByte() catch {};
    } else {
        var buf = [_]u8{0} ** 50;
        const path = try std.fmt.bufPrint(&buf, "/dev/fd/{}", .{original.handle});
        var new = try std.fs.openFileAbsolute(path, .{.mode = .write_only});
        defer new.close();
        try new.writer().print("Hello from {}\n", .{std.os.linux.getpid()});
    }
}

The surprising behaviour happens when I comment out line 8. When it’s not commented out, the file isn’t seen on the filesystem while the program waits in line 18, but if it’s commented out, the file is actually seeable. I also only get the complaint of trying to delete it if it’s not commented out.

Does somebody have an idea why this might be?

Won’t the defer with the deleteFile run when the child process finishes and therefore the file will be deleted after waitpid returns?

You have defer of deleteFile in scope before starting the child process. If fork succeeds, then you have two processes executing the deferred deleteFile at their ends of main.

As @squeek502 already stated, waitpid then orders the two processes, such that child will finish first and therefore delete the file.

The parent process can still read that file, since it had it already open. Linux actually deletes files only after the last process having them open closes them. Nontheless, file deletions remove them immediately from directory listings. So you can’t easily see that file despite the parent process having it still open for reading.

Yeah ok, fair enough, I haven’t thought of that.

I should maybe stop late night coding after working for a full day…

1 Like