Re: [PATCH] timespec_get.3: new page (timespec_get(), timespec_getres())

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Kernel Documentation]     [Netdev]     [Linux Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux