Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions lib/std/os/linux.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1919,6 +1919,39 @@ pub fn gettid() pid_t {
return @intCast(@as(u32, @truncate(syscall0(.gettid))));
}

pub const TimedWaitError = error{
/// Timeout supplied was reached.
TimeElapsed,
/// Call was interrupted by a signal not in supplied sigset.
OtherSignal,
/// Value in timeout is invalid
InvalidTimeout,
};

/// Suspends the calling thread until one of the signals in set is pending or the specified timeout is reached (If one
/// of the signals in set is already pending for the calling thread, returns immediately.) Removes the signal from the
/// set of pending signals and returns that signal. If the info argument is non-NULL, that buffer is used to return
/// siginfo_t of the signal. If multiple signals in set are pending for the caller, the signal returned is determined
/// according to the usual ordering rules
pub fn sigtimedwait(
sigset: sigset_t,
siginfo: ?*siginfo_t,
/// specifies a minimum interval for which the thread is suspended waiting for a signal. (This
/// interval will be rounded up to the system clock granularity, and kernel scheduling delays mean that the interval
/// may overrun by a small amount.)
timeout: *const timespec,
) TimedWaitError!SIG {
const sig_num = syscall4(.rt_sigtimedwait, @intFromPtr(&sigset), @intFromPtr(siginfo), @intFromPtr(timeout), NSIG / 8);

return switch (E.init(sig_num)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functions in std.os.linux do not to switch on errno values. This function should probably just return sig_num as an usize and another function in std.os.linux.wrapped or std.posix can then call this function and switch on the errno.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

else => |err| return std.os.unexpectedErrno(err),

else => |err| return unexpectedErrno(err),

else => |err| return unexpectedErrno(err),

I thought the exact same thing, but decided to keep it here mostly because posix as it is now isn't long for the repo.

.SUCCESS => @enumFromInt(sig_num),
.AGAIN => error.TimeoutElapsed,
.INTR => error.OtherSignal,
.ENVAL => error.InvalidTimeout,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this a classic case of programmer error?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to #6389 this EINVAL should probably map to Unexpected? (I'm a fan of mapping the errnos 1:1 like the original PR here, but I believe 6389 is the current Zig plan of record.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this a classic case of programmer error?

That is more likely, but I'm not a fan of the current stdlib behavior of cutting it's own head off when something unexpected happens. I can replace this with invalidApiUsage() but I'd much rather expose the same API semantics that linux does. given this is a linux syscall.

Someone wanna make the call and I'll update the diff?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative would be using something like Io.Duration, and converting it internally. Then it's a prevented bug, instead of one that crashes the app... unless linux does something weird, and rejects a valid timeout?

else => |err| return std.posix.unexpectedErrno(err),
};
}

pub fn sigprocmask(flags: u32, noalias set: ?*const sigset_t, noalias oldset: ?*sigset_t) usize {
return syscall4(.rt_sigprocmask, flags, @intFromPtr(set), @intFromPtr(oldset), NSIG / 8);
}
Expand Down