Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std.posix.timerfd_create can reach unreachable code #20334

Open
Cydox opened this issue Jun 17, 2024 · 2 comments
Open

std.posix.timerfd_create can reach unreachable code #20334

Cydox opened this issue Jun 17, 2024 · 2 comments
Labels
bug Observed behavior contradicts documented or intended behavior os-linux standard library This issue involves writing Zig code for the standard library.
Milestone

Comments

@Cydox
Copy link
Contributor

Cydox commented Jun 17, 2024

Zig Version

0.14.0-dev.58+254a3ba9d

Steps to Reproduce and Observed Behavior

This example program will reach unreachable code in std.posix.timerfd_create:

const std = @import("std");

pub fn main() !void {
    const timer_fd = try std.posix.timerfd_create(std.os.linux.CLOCK.TAI, .{});
    _ = timer_fd;
}

Expected Behavior

On Linux, the timerfd_create syscall will return EINVAL if clockid is not one of CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM. This is a stricter list of allowed clock ids than for some other syscalls, for example CLOCK_TAI, while otherwise a valid clock id, is not valid here.
Kernel source: https://github.com/torvalds/linux/blob/14d7c92f8df9c0964ae6f8b813c1b3ac38120825/fs/timerfd.c#L426

FreeBSD (#20308): On FreeBSD only CLOCK_REALTIME, CLOCK_MONOTONIC, and CLOCK_UPTIME are allowed, which is also a subset of the clock ids on FreeBSD. (CLOCK_UPTIME is not listed as allowed in the man pages, but the source code allows it and my testing shows that it is working)
https://github.com/freebsd/freebsd-src/blob/1389314d53531e06c7ec02406b0addf7d77e7db7/sys/kern/sys_timerfd.c#L447
https://man.freebsd.org/cgi/man.cgi?query=clock_gettime

As I see it, there are two alternatives:

  1. std.posix.timerfd_create should take an enum as clock id (which will have to be specific to timerfd_create, as it uses a smaller subset) instead of an i32
  2. return the error instead of making it unreachable

I'm very much in favor of option 1.

@Cydox Cydox added the bug Observed behavior contradicts documented or intended behavior label Jun 17, 2024
@andrewrk andrewrk added standard library This issue involves writing Zig code for the standard library. os-linux labels Aug 14, 2024
@andrewrk andrewrk added this to the 0.16.0 milestone Aug 14, 2024
@chrboesch
Copy link
Contributor

The problem is caused by the fact that in Zig the Linux functions timerfd_create(int clockid,.. and clock_gettime(clockid_t clk_id,... are served from the enum clockid_t, which is wrong. In the Linux function timerfd_create it's just an int. But to Zig's credit, the header file timerfd.h also only includes the header file time.h and the man page timercreate_fd(2) then refers to the constants within the header file and gives hints as to which ones to use. One of the unfortunately common confusions in Linux that we should try to avoid in Zig.

Therefore my suggestion, and I think this is what the creator of this issue means, is to create a second enum clock_id with only the valid entries for timerfd_create:

pub const CLOCK_ID = clock_id;

pub const clock_id = enum(u32) {
    REALTIME = 0,
    MONOTONIC = 1,
    _,
};

So we can enter all valid clock IDs ourselves, regardless of what is written in the man page, as @alexrp suggested here: #21347 (comment)

@chrboesch
Copy link
Contributor

chrboesch commented Sep 12, 2024

I have enhanced the PR to solve the issue with posix.timerfd_create() and additional posix.clock_gettime() now returns the time_spec.

Now this works with an new enum, wich only includes the possible values:

const tfd = try std.posix.timerfd_create(std.os.linux.CLOCK_ID.REALTIME, .{});
defer std.posix.close(tfd);

and also this works with time_spec as return value:

const time_spec = try std.posix.clock_gettime(std.os.linux.CLOCK.REALTIME);
std.debug.print("time_spec = {any}\n", .{time_spec});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior os-linux standard library This issue involves writing Zig code for the standard library.
Projects
None yet
Development

No branches or pull requests

3 participants