|
Message-ID: <CAKzaEUdDGPO7Pi_QYjmh62Vh-M7vm6chPOuX8uwYhp6rAOEGRw@mail.gmail.com> Date: Thu, 30 Aug 2018 07:30:28 -0700 From: Peter Hurley <peter@...aki.com> To: musl@...ts.openwall.com Subject: Re: [PATCH] Preserve select() behavior on arm64 On Wed, Aug 29, 2018 at 3:56 PM, Rich Felker <dalias@...c.org> wrote: > On Wed, Aug 29, 2018 at 06:42:47PM -0400, Rich Felker wrote: >> On Fri, May 25, 2018 at 01:52:40PM -0700, Peter Hurley wrote: >> > On Linux, all the select-related syscalls update the timeout value to >> > indicate how much elapsed time the syscall consumed, and many programs >> > expect this behavior when running on Linux. >> > >> > Newer archs like arm64 have deprecated the select syscall because the >> > pselect syscall is a superset implementation of the select syscall. >> > >> > A complication of implementing select() with the pselect syscall is >> > that the timeouts are specified in different units; select() accepts >> > a struct timeval ptr whereas the pselect syscall takes a struct >> > timespec ptr. These are trivial convertible; struct timeval is >> > specified in seconds + microseconds and struct timespec is in >> > seconds + nanoseconds. >> > >> > For kernel configurations without select syscall available, update the >> > caller's struct timeval argument after the pselect syscall. >> > --- >> > src/select/select.c | 17 +++++++++-------- >> > 1 file changed, 9 insertions(+), 8 deletions(-) >> > >> > diff --git a/src/select/select.c b/src/select/select.c >> > index 7b5f6dcf7a53..45d4cb7a3d0a 100644 >> > --- a/src/select/select.c >> > +++ b/src/select/select.c >> > @@ -12,15 +12,16 @@ int select(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict >> > #else >> > syscall_arg_t data[2] = { 0, _NSIG/8 }; >> > struct timespec ts; >> > + int result; >> > if (tv) { >> > - if (tv->tv_sec < 0 || tv->tv_usec < 0) >> > - return __syscall_ret(-EINVAL); >> > - time_t extra_secs = tv->tv_usec / 1000000; >> > - ts.tv_nsec = tv->tv_usec % 1000000 * 1000; >> > - const time_t max_time = (1ULL<<8*sizeof(time_t)-1)-1; >> > - ts.tv_sec = extra_secs > max_time - tv->tv_sec ? >> > - max_time : tv->tv_sec + extra_secs; >> > + ts->tv_sec = tv->tv_sec; >> > + ts->tv_nsec = tv->usec * 1000; >> > } >> > - return syscall_cp(SYS_pselect6, n, rfds, wfds, efds, tv ? &ts : 0, data); >> > + result = syscall_cp(SYS_pselect6, n, rfds, wfds, efds, tv ? &ts : 0, data); >> > + if (tv) { >> > + tv->tv_sec = ts->tv_sec; >> > + tv->tv_usec = ts->tv_nsec / 1000; >> > + } >> > + return result; >> > #endif >> > } >> > -- >> > 2.14.2 >> >> Sorry for not replying to this sooner. I was unsure what to say at >> first and then it just slipped my mind to go back to it. > > I think the patch is also incorrect as written. It removes the code > for handling timeval values which would be out of range if naively > converted to timespec (either<0 or usec>999999, and overflows). I'm > not sure how SYS_select handles updating the remaining time in the > overflow cases, so if you're trying to duplicate it, researching that > is probably called for. It may be right to just normalize it like > you're doing when converting back, but this will effectively report > the wrong amount of elapsed time if tv_sec+tv_usec/1000000 overflows. > > Rich Linux returns -EINVAL for not normalized timespec and timeval inputs. Regards, Peter Hurley
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.