Why `close(self: File)`, but `close(self: *Dir)`?

It looks the fs.File and fs.Dir both has only one Handle field.

Okay, I see the implement of Dir.close

pub fn close(self: *Dir) void {
    posix.close(self.fd);
    self.* = undefined;
}

What is the purpose of the last line?

Generaly assigning undefined used to catch mistakes using valgrind

const std = @import("std");

pub fn main() !void {
    var dir = try std.fs.cwd().openDir(".", .{});
    dir.close();
    dir.close();
}
valgrind ./main
==348296== Memcheck, a memory error detector
==348296== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==348296== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==348296== Command: ./main
==348296==
==348296== Syscall param close(fd) contains uninitialised byte(s)
==348296==    at 0x1080678: os.linux.x86_64.syscall1 (x86_64.zig:28)
==348296==    by 0x1081ED7: os.linux.close (linux.zig:1296)
==348296==    by 0x106CF73: posix.close (posix.zig:275)
==348296==    by 0x106E036: fs.Dir.close (Dir.zig:789)
==348296==    by 0x10DDF25: main.main (main.zig:6)
==348296==    by 0x10DDDDA: callMain (start.zig:656)
==348296==    by 0x10DDDDA: callMainWithArgs (start.zig:616)
==348296==    by 0x10DDDDA: start.posixCallMainAndExit (start.zig:571)
==348296==    by 0x10DD98D: (below main) (start.zig:271)
==348296==
==348296== Warning: invalid file descriptor -1431655766 in syscall close()
thread 348296 panic: reached unreachable code

In this case its not really useful since it is caught even without valgrind

./main
thread 348578 panic: reached unreachable code
/home/andrewkraevskii/.zvm/master/lib/std/posix.zig:276:18: 0x106cfa3 in close (main)
        .BADF => unreachable, // Always a race condition.
                 ^
/home/andrewkraevskii/.zvm/master/lib/std/fs/Dir.zig:789:16: 0x106e036 in close (main)
    posix.close(self.fd);
               ^
/home/andrewkraevskii/projects/ups/main.zig:6:14: 0x10ddf25 in main (main)
    dir.close();
             ^
/home/andrewkraevskii/.zvm/master/lib/std/start.zig:656:37: 0x10dddda in posixCallMainAndExit (main)
            const result = root.main() catch |err| {
                                    ^
/home/andrewkraevskii/.zvm/master/lib/std/start.zig:271:5: 0x10dd98d in _start (main)
    asm volatile (switch (native_arch) {
    ^
???:?:?: 0x0 in ??? (???)
Aborted (core dumped)
2 Likes

Plus, in the future, Zig will be able to detect and panic on undefined value usage in debug mode:

1 Like