-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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: Rewriting enums to seperate clock IDs for clock_gettime() and timerfd_create() #21347
base: master
Are you sure you want to change the base?
Conversation
In the linux kernel header file (time.h) is the note, that the driver implementing the clock IDs - SGI_CYCLE - TAI got removed. Therefore, calling timerfd_create() with these IDs will result in an error. So I disabled them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks fine to me.
However, I do not believe this fixes #20334 because there are still more clocks defined here than timerfd_create()
will accept. And it seems like there needs to be some discussion on that issue as to how that should be addressed.
I have tried every other clock ID on my linux computer and it works fine and as expected. And since the clock IDs are defined as enums, contrary to the assumption of the thread creator, you can only select the ones entered. So it will definitely fix the issue. |
So just to be clear, even clocks like |
The fact that you ask means it doesn't work on your computer. Let me do some testing on different computers. |
No no, I haven't actually tried. I'm only asking because those specifically are somewhat special clocks, so I just wouldn't take it for granted that they work with |
First of all, thanks for your skepticism. It was my bad that I did some quick tests in C on my Gentoo with self-compiled kernel. And that I mixed timerfd_create with getclock_time because there is no separation in the header file time.h. Interestingly, the timers even work in Zig even though they shouldn't. But only on my self-compiled kernel. And sometimes only with root rights. However, the man page timerfd_create(2) says there are actually only two valid timers: CLOCK_REALTIME and CLOCK_MONOTONIC. So, I think we should limit the enum of these clock IDs, because it doesn't make sense if a timer sometimes works and sometimes doesn't. And it's hard to explain that you can achieve this with some special kernel settings. 😉 What surprises me a little, however, is that the equivalent POSIX command is 'timer_create'. And it also knows CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID, but is triggered by different Linux commands. In other words, the over all change should not only be limited to restricting the enum, but also to correctly mapping the POSIX command. TL;DR Addendum: Since clock_id is also used in Zig for clock_gettime, this is a bit more complicated. We therefore need to have a second enum just for timercreate_fd. That's probably what the issue creator meant? Addendum 2: To add to the confusion, Zig uses Addendum 3: It's not Zig's fault, it's Linux's fault. There, the term 'clockid' is used in the same way in different contexts, which contributes to this confusion. These are the things that contribute to instability and errors in operation because developers mistakenly confuse the two. I'll think about how we can make this better for Zig. |
It wouldn't surprise me if some distros disable those clocks I mentioned for non-superusers out of security concerns or something like that. But I'm just guessing here.
Generally speaking, the Linux kernel code is the source of truth; the man pages are sometimes incomplete or wrong. I think we should base our decision on what the kernel code is written to allow. If it is the case (and I don't know if it is) that the kernel can return I think all the Linux system calls that take clock IDs should be checked to see what's allowed before we decide what to do here (other than removing |
Ok, I removed the "fixes #20334", because it doesn't. So the PR is valid. And then we should discuss in the issue what we should do to solve the problem in general. |
…h clock_gettime() As explained in ziglang#2034 and also discussed here, now the complete adjustment to resolve the issue.
calling for clock_gettime() for getting the timespec now as return value.
forgotten changes for local testing This reverts commit 6c0a56d.
system.timerfd_create should get the right integer param.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the cleanup of clock_gettime()
. I've got a couple drive-by comments, but feel free to ignore them if they don't make sense to you.
// * The driver implementing this got removed. The clock ID is kept as a | ||
// * place holder. Do not reuse! | ||
// Therefore, calling clock_gettime() with these IDs will result in an error. | ||
// SGI_CYCLE = 10, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically these could be useful if someone wants to compile a Zig program to run against an old Linux kernel that supports these old clocks? (I suspect that's really unlikely in this case though?) Anyway, it seems a bit odd for Zig to only track what is currently supported, so maybe its just sufficient to add a comment that these clocks are not supported on modern systems?
SGI_CYCLE = 10, // Linux dropped support for this clock in the v4.13 timeframe
TAI = 11, // Linux dropped support for this clock in the v4.13 timeframe
I may be missing some context on these clocks, so feel free to ignore this if its not compelling to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TAI_CLOCK was designed as CLOCK_REALTIME(UTC) + tai_offset, but tai_offset was always 0. So there is no point in using this clock, and no one did.
SGI_CYCLE was for Silicon Graphics (SGI) workstations, which are probably no longer in use, so it makes sense to disable these two.
|
||
pub const CLOCK_ID = clock_id; | ||
|
||
pub const clock_id = enum(u32) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a short comment here and on clockid_t differentiating them? (I think just labelling which API/syscall they're aimed at would be sufficient? clock_gettime vs timerfd_create?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, makes sense.
lib/std/posix/test.zig
Outdated
@@ -1121,7 +1121,7 @@ test "access smoke test" { | |||
test "timerfd" { | |||
if (native_os != .linux) return error.SkipZigTest; | |||
|
|||
const tfd = try posix.timerfd_create(.MONOTONIC, .{ .CLOEXEC = true }); | |||
const tfd = try posix.timerfd_create(posix.clock_id.MONOTONIC, .{ .CLOEXEC = true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The posix.clock_id.
prefix shouldn't be necessary here, Zig should pick the right .MONOTONIC from the type signature of timerfd_create.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok.
…it. So the declaration of the enum must be i32 for the C export.
Now this PR fixes #20334. |
@@ -2054,10 +2054,10 @@ pub fn eventfd(count: u32, flags: u32) usize { | |||
return syscall2(.eventfd2, count, flags); | |||
} | |||
|
|||
pub fn timerfd_create(clockid: clockid_t, flags: TFD) usize { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't looked at the PR in a few days so I might be missing some context here - why are we changing this to an integer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I based my work on the kernel sources, there it is an integer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't mean it quite that literally when I said the kernel code should be the basis for our decision here. 🙂 We do use enums in syscall wrappers when the set of acceptable values is known ahead of time - which I think is the case here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was unsure but can change that.
In the linux kernel header file (time.h) is the note, that the driver implementing the clock IDs
got removed. Therefore, calling timerfd_create() with these IDs will result in an error. So I disabled them.