On Fri, Sep 06, 2024 at 02:16:40AM +0200, Alejandro Colomar wrote: > Hi Ahelenia, > > On Thu, Sep 05, 2024 at 01:41:58PM GMT, Ahelenia Ziemiańska wrote: > > If you're wondering how errno is affected, so am I; no-one really says; > > quoth POSIX: > > If base is TIME_UTC, the members of ts shall be set to the same values as would be set by a call > > to clock_gettime(CLOCK_REALTIME, ts). > > > > RETURN VALUE > > If the timespec_get( ) function is successful it shall return the non-zero value base; otherwise, it > > shall return zero. > > > > ERRORS > > See DESCRIPTION. > > > > But this is a moot point since clock_gettime() can't fail anyway > > (glibc doesn't even check the error). > > I see at least the following errors in clock_gettime(2): > > EFAULT tp points outside the accessible address space. This one would be real..but clock_gettime() is widely implemented as a vDSO routine so it's a segfault on those architectures. (And for this reason POSIX never outlines EFAULT by name.) Thus, I'd call this just UB, not an EFAULT-style "error". glibc doesn't check for errors, musl will return 0 here tho. > EINVAL The clockid specified is invalid for one of two reasons. > EINVAL The clockid specified in a call to clock_settime() is not a > settable clock. > ENODEV The hot‐pluggable device (like USB for example) represented > ENOTSUPThe operation is not supported by the dynamic POSIX clock Not possible, since CLOCK_REALTIME is always valid. > EOVERFLOW The timestamp would not fit in time_t range. I'm choosing to not see it, especially in in a.d. 2024 for a novel API. But, again, glibc doesn't check for errors, musl will return 0 tho. POSIX says > If the number of seconds will not fit in an object of > type time_t, the function shall return zero. But it defines t_g(T_U) as "the members of ts shall be set to the same values as would be set by a call to clock_gettime(CLOCK_REALTIME, ts)." and then adds that overflow sentence. Which doesn't indicate an errno-setting condition to me? It's not defined as /literally/ calling clock_gettime(), and the overflow sentence protects from the only error condition in clock_gettime(). So this implies to me that errno isn't set? To test this, I built a test program on buster/i386, then ran it on a system with time set to 2^31 and 2^32. I can't really trigger clock_gettime()'s EOVERFLOW... anyway, ever? Now, musl ships compat/time32/timespec_get_time32.c, which does this: int __timespec_get_time32(struct timespec32 *ts32, int base) { struct timespec ts; int r = timespec_get(&ts, base); if (!r) return r; if (ts.tv_sec < INT32_MIN || ts.tv_sec > INT32_MAX) { errno = EOVERFLOW; it's unclear to me when this wrapper is used, however. And I'd say it's... wrong per POSIX? Actually? A little bit? Bypassing the vDSO so timespec_get() actually runs a syscall, and giving it an invalid pointer (strace says EFAULT!), got me 0/errno=0. Which I'd say is correct per POSIX? C says Returns If th etimespec_get function is successful it returns the nonzero value base; otherwise, it returnszero. and doesn't mention errno at all. So from this I'm going to opine that (a) glibc is right to not set errno on -EFAULT, (b) musl is wrong to set errno when it detects EOVERFLOW, but also it doesn't matter. All BSD implementations I looked through are if(clock_gettime() == -1) return 0; return base; and I don't think they have errno filtering that harsh. So idk. I think it's fine Scissor-patch below. Best, -- >8 -- Subject: [PATCH] timespec_get.3: new page (timespec_get(), timespec_getres()) Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@xxxxxxxxxxxxxxxxxx> --- man/man3/timespec_get.3 | 95 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 man/man3/timespec_get.3 diff --git a/man/man3/timespec_get.3 b/man/man3/timespec_get.3 new file mode 100644 index 000000000..bd32a600c --- /dev/null +++ b/man/man3/timespec_get.3 @@ -0,0 +1,95 @@ +'\" t +.\" SPDX-License-Identifier: 0BSD +.\" +.TH timespec_get 3 (date) "Linux man-pages (unreleased)" +.SH NAME +timespec_get, timespec_getres \- standard C clock and time functions +.SH LIBRARY +Standard C library +.RI ( libc ,\~ \-lc ), +.SH SYNOPSIS +.nf +.B #include <time.h> +.P +.BI "int timespec_get(struct timespec *" res ", int " base ); +.BI "int timespec_getres(struct timespec *" tp ", int " base ); +.fi +.P +.RS -4 +Feature Test Macro Requirements for glibc (see +.BR feature_test_macros (7)): +.RE +.P +.BR timespec_get (): +.nf + _ISOC11_SOURCE || _ISOC2X_SOURCE + || __STDC_VERSION__ >= 201112L + || /* glibc <= 2.19: */ _BSD_SOURCE || _SVID_SOURCE +.P +.BR timespec_getres (): +.nf + _ISOC2X_SOURCE || __STDC_VERSION__ > 201710L +.fi +.SH DESCRIPTION +.BI timespec_get\fR(\fP tp ", TIME_UTC)" +is defined as +.IR "clock_gettime(CLOCK_REALTIME, tp)" . +.P +.BI timespec_getres\fR(\fP res ", TIME_UTC)" +is equivalent to +.IR "timespec_getres(CLOCK_REALTIME, res)" . +.P +.BR TIME_UTC +is universally guaranteed to be a valid +.IR base , +and is the only one supported under Linux. +.SH RETURN VALUE +.B 0 +if base is unsupported or the call failed, otherwise +.IR base . +.SH ERRORS +Some C libraries +.I may +set +.I errno +to the same value as would be set by +.BR clock_gettime (2)/ clock_getres (2). +Neither C nor POSIX specify this, but they don't really indicate this shouldn't happen, either. +Don't rely on this. +.SH ATTRIBUTES +For an explanation of the terms used in this section, see +.BR attributes (7). +.TS +allbox; +lbx lb lb +l l l. +Interface Attribute Value +T{ +.na +.nh +.BR timespec_get (), +.BR timespec_getres () +T} Thread safety MT-Safe +.TE +.SH STANDARDS +.TP +.BR timespec_get () +.TQ +.B TIME_UTC +C23 (though note that C doesn't specify the time epoch), +POSIX.1-2024. +.TP +.BR timespec_getres () +C23. +.SH HISTORY +.TP +.BR timespec_get () +.TQ +.B TIME_UTC +C11, POSIX.1-2024, glibc 2.16, musl 1.1.10. +.TP +.BR timespec_getres () +C23, glibc 2.34. +.SH SEE ALSO +.BR clock_gettime (2), +.BR clock_getres (2) -- 2.39.2
Attachment:
signature.asc
Description: PGP signature