On Wed, Jul 21, 2021 at 04:00:51AM +0200, Ingo Schwarze wrote: > Hi Scott, > > Scott Cheloha wrote on Tue, Jul 20, 2021 at 05:20:16PM -0500: > > > The nanosleep.2 page could use some cleanup. Here's a bunch of fixes, > > rewrites, etc. > > > > I've included my notes on the changes below. I have some (mostly > > stylistic) questions in there, too. > > Thanks for explaining what you are doing. I'm snipping what i agree > with as well as what i have no opinion on and trust you on, but that > doesn't mean that mentioning it was useless. > > > Should we reference sigaction(2) here alongside SA_RESTART? e.g.: > > > > ... even if SA_RESTART is set for the interrupting signal > > (see sigaction(2) for further details). > > [...] > > Maybe something like: > > ... even if SA_RESTART was set with sigaction(2) for the > interrupting signal. > > Your call, i would say.
I like that. Using this snippet now. > > I'm unsure about the correct voice here. Should nanosleep actively > > return values? Or should values "be returned"? > > Both are acceptable. In general, and not just in manual pages, > prefer the active voice when both work equally well. Staying active, then. > > I'm unclear on whether I need the indent here in the .Bd block. I > > think it looks better than unindented code, but maybe I'm flouting > > some practice we have. > > Using tabs is permitted inside .Bd -literal and .Bd -unfilled. > They should definitely be used for indenting the bodies of for, > while, and if. > > Whether you indent the whole thing depends on what looks better. > When the code is relatively narrow, indenting the whole example > is often a good idea. When the code contains very long lines, > not indenting the whole example may be better. > > If you choose to indent, i have no strong prefernce whether you > do it with tabs or with .Bd -literal -offset indent; maybe i very > slightly prefer the latter, because the global indentation is > a formatting choice rather than part of the displayed code. > But i really wouldn't complain about either. deraadt@ has vetoed the examples so this is no longer an issue. > > ERRORS > > - Simplify the opening sentence. Yeesh, what a mouthful. > > Indeed, ERRORS should not repeat the content of RETURN VALUES. > > > Unsure if a second EFAULT case for remainder is a good thing here. > > Strictly speaking, NULL is not a valid part of the process address > > space. Maybe that's too pedantic? > > I don't think you can be too pedantic about where NULL is allowed > and where it isn't. That's a notorious source of bugs, so precision > about NULL is usually a good thing. Keeping it, then. > > Also, do we have a more standard "boilerplate" sentence for EFAULT? > > Judging from "man -l /usr/share/man/man2/*.2", the most common > wording is: > > [EFAULT] foo points outside the process's allocated address space. > > But i don't really i like that. The word "allocated" makes me wonder > because it sounds too much like malloc(3) for my taste. > Usually, pointers to automatic and to static objects are acceptable, > too, and are those "allocated"? Some might say they are not. > Besides, "process's" looks awkward. > > These occur, too: > > [EFAULT] The foo parameter is not in a valid part of the user > address space. > > [EFAULT] foo references invalid memory. > > [EFAULT] The name parameter specifies an area outside the > process address space. > > [EFAULT] foo points to an illegal address. > > [EFAULT] The userspace address uaddr is invalid. > > [EFAULT] Part of buf points outside the process's allocated > address space. > > [EFAULT] The buf parameter points to an invalid address. > > [EFAULT] The argument foo specifies an invalid address. > > [EFAULT] The foo parameter specified a bad address. > > [EFAULT] The foo parameter points to memory not in > a valid part of the process address space. > > [EFAULT] The address specified for foo is invalid. > > [EFAULT] An argument address referenced invalid memory. > > In errno(2): > 14 EFAULT Bad address. The system detected an invalid address in > attempting to use an argument of a call. > > [EFAULT] There was an error reading or writing the kevent > structure. > > Quite a mess, i would say. > > I think trying to explain over and over again what an invalid address > is, in each and every manual page, is neither reasonable nor feasible - > i'm not convinced the rules are really simple given how many types > of valid memory there are: static, stack, heap, ... > > So i'd probably settle for a concise, simple wording, and i think > i like this one best: > > [EFAULT] foo points to an invalid address. > > What is valid can easily depend on the function being called and > even on other function arguments; the same address can easily be > valid for reading a handful of bytes but invalid for reading > kilobytes, let alone megabytes of data. > > Please don't say "illegal" (it's not a crime) nor "bad". Thank you for diving into this. Given deraadt@'s response I'm just going to leave the existing language. Somebody else can unify the language for all the EFAULT cases as a future summer project, I guess. > > SEE ALSO > > - Cross reference sigaction(2). We mention SA_RESTART in the > > description. > > Yes, that seems helpful. > > Users of nanosleep(2) *should* consider signal handling, and sigaction(2) > is the canonical place to learn about that. > > > - I'm pretty sure nanosleep() is a POSIX invention, so note that it > > really first appeared in POSIX.1b (realtime extensions), > > That would be quite unusual; as a rule, the Austin group categorically > refuses to standardize anything that doesn't at least have two > implementations in relevant real-world operating systems. > Consequently, we almost never have .St below HISTORY. > > Then again, i believe you know this stuff, so i trust you if you > say POSIX invented this and did not merely adopt it from some > commercial UNIX system. And if that is true, if standardization > really predates implementation in this case, then using .St > below HISTORY is indeed the right thing to do. I guess I will need to dig into it a bit. Finding the text of the really early documents, prior to SUSv2, is tricky. > > If someone can find nanosleep() in the wild before 1993 we can fix > > the attribution. > > Fair enough. You can also ask millert@ if you have doubts, he often > remembers details about POSIX that many others don't. Sure thing. > See below in-line for some nits. Getting rid of \\ is mandatory; > the rest are only suggestions. > > [...] > > > Index: nanosleep.2 > > =================================================================== > > RCS file: /cvs/src/lib/libc/sys/nanosleep.2,v > > retrieving revision 1.16 > > diff -u -p -r1.16 nanosleep.2 > > --- nanosleep.2 31 Dec 2018 18:54:00 -0000 1.16 > > +++ nanosleep.2 20 Jul 2021 22:14:50 -0000 > > @@ -41,53 +41,114 @@ > > .Ft int > > .Fn nanosleep "const struct timespec *timeout" "struct timespec *remainder" > > .Sh DESCRIPTION > > +The > > .Fn nanosleep > > -suspends execution of the calling process for the duration specified by > > +function suspends execution of the calling thread for at least the > > +duration specified by > > .Fa timeout . > > -An unmasked signal will cause it to terminate the sleep early, > > -regardless of the > > +Delivery of an unmasked signal to the calling thread will terminate the > > s/will terminate/terminates/ is enough; "will" is needed rarely > in manual pages. Changed. > > +sleep early, > > +even if > > .Dv SA_RESTART > > -value on the interrupting signal. > > +is set for the interrupting signal. > > .Sh RETURN VALUES > > -If the > > +If > > .Fn nanosleep > > -function returns because the requested duration has elapsed, the value > > -returned will be zero. > > +sleeps the full > > +.Fa timeout > > +without interruption it returns 0. > > +If > > +.Fa remainder > > +is > > +.Pf non- Dv NULL > > Prefixing non- like this is acceptable, but not particularly nice. > I would like this better: > > Unless > .Fa remainder > is > .Dv NULL , Changed. > > +it is set to zero. > > .Pp > > -If the > > +If > > .Fn nanosleep > > -function returns due to the delivery of a signal, the value returned > > -will be \-1, and the global variable > > +is interrupted by a signal it returns -1 and the global variable > > .Va errno > > -will be set to indicate the interruption. > > +is set to > > +.Dv EINTR . > > If > > .Fa remainder > > -is non-null, the timespec structure it references is updated to contain the > > -unslept amount (the requested duration minus the duration actually slept). > > -.Sh ERRORS > > -If any of the following conditions occur, the > > +is > > +.Pf non- Dv NULL > > Unless... as above. Changed. > [...] > > Regarding the following, why not be very explicit, considering that > the rules differ for both cases? > > > .It Bq Er EFAULT > > -Either > > .Fa timeout > > -or > > +pointed to memory that is not a valid part of the process address space. > > .Fa timeout > was > .Dv NULL > or pointed to an invalid address. > > > +.It Bq Er EFAULT > > .Fa remainder > > -points to memory that is not a valid part of the process address space. > > +was > > +.Pf non- Dv NULL > > +and pointed to memory that is not a valid part of the process address > > space. > > .Fa remainder > was not > .Dv NULL > and pointed to an invalid address. As I said before, I'm just going to keep the existing language. -- Okay, updated patch attached. One additional change: - Escape the minus sign for "-1". Index: nanosleep.2 =================================================================== RCS file: /cvs/src/lib/libc/sys/nanosleep.2,v retrieving revision 1.16 diff -u -p -r1.16 nanosleep.2 --- nanosleep.2 31 Dec 2018 18:54:00 -0000 1.16 +++ nanosleep.2 21 Jul 2021 15:57:55 -0000 @@ -41,53 +41,71 @@ .Ft int .Fn nanosleep "const struct timespec *timeout" "struct timespec *remainder" .Sh DESCRIPTION +The .Fn nanosleep -suspends execution of the calling process for the duration specified by +function suspends execution of the calling thread for at least the +duration specified by .Fa timeout . -An unmasked signal will cause it to terminate the sleep early, -regardless of the +Delivery of an unmasked signal to the calling thread terminates the +sleep early, +even if .Dv SA_RESTART -value on the interrupting signal. +is set with +.Xr sigaction 2 +for the interrupting signal. .Sh RETURN VALUES -If the +If .Fn nanosleep -function returns because the requested duration has elapsed, the value -returned will be zero. +sleeps the full +.Fa timeout +without interruption it returns 0. +Unless +.Fa remainder +is +.Dv NULL , +it is set to zero. .Pp -If the +If .Fn nanosleep -function returns due to the delivery of a signal, the value returned -will be \-1, and the global variable +is interrupted by a signal it returns \-1 and the global variable .Va errno -will be set to indicate the interruption. -If +is set to +.Dv EINTR . +Unless .Fa remainder -is non-null, the timespec structure it references is updated to contain the -unslept amount (the requested duration minus the duration actually slept). -.Sh ERRORS -If any of the following conditions occur, the +is +.Dv NULL , +it is set to the unslept portion of the +.Fa timeout . +.Pp +Otherwise, .Fn nanosleep -function shall return \-1 and set +returns \-1 and the global variable .Va errno -to the corresponding value. +is set to indicate the error. +.Sh ERRORS +.Fn nanosleep +will fail if: .Bl -tag -width Er .It Bq Er EINTR -.Fn nanosleep -was interrupted by the delivery of a signal. +The call is interrupted by the delivery of a signal. .It Bq Er EINVAL .Fa timeout -specified a nanosecond value less than zero or greater than or equal to -1000 million, +specifies a nanosecond value less than zero or greater than or equal to +one billion, or a second value less than zero. .It Bq Er EFAULT -Either .Fa timeout -or -.Fa remainder points to memory that is not a valid part of the process address space. +.It Bq Er EFAULT +.Fa remainder +is not +.Dv NULL +and points to memory that is not a valid part of the process address space. .El .Sh SEE ALSO .Xr sleep 1 , +.Xr sigaction 2 , .Xr sleep 3 .Sh STANDARDS The @@ -97,17 +115,23 @@ function conforms to .Sh HISTORY The predecessor of this system call, .Fn sleep , -appeared in -.At v3 , -but was removed when +first appeared in +.At v3 . +It was removed in +.At v7 +and replaced with a C library implementation based on .Xr alarm 3 -was introduced into -.At v7 . +and +.Xr signal 3 . +.Pp The .Fn nanosleep -system call has been available since +function first appeared in +.St -p1003.1b-93 . +.Pp +This implementation of +.Fn nanosleep +first appeared in .Nx 1.3 and was ported to -.Ox 2.1 -and -.Fx 3.0 . +.Ox 2.1 .