1998-12-06 08:44:12 +08:00
|
|
|
/* Guts of both `select' and `poll' for Hurd.
|
2024-01-02 02:12:26 +08:00
|
|
|
Copyright (C) 1991-2024 Free Software Foundation, Inc.
|
1998-12-06 08:44:12 +08:00
|
|
|
This file is part of the GNU C Library.
|
|
|
|
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
2001-07-06 12:58:11 +08:00
|
|
|
modify it under the terms of the GNU Lesser General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2.1 of the License, or (at your option) any later version.
|
1998-12-06 08:44:12 +08:00
|
|
|
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
2001-07-06 12:58:11 +08:00
|
|
|
Lesser General Public License for more details.
|
1998-12-06 08:44:12 +08:00
|
|
|
|
2001-07-06 12:58:11 +08:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
2012-02-10 07:18:22 +08:00
|
|
|
License along with the GNU C Library; if not, see
|
Prefer https to http for gnu.org and fsf.org URLs
Also, change sources.redhat.com to sourceware.org.
This patch was automatically generated by running the following shell
script, which uses GNU sed, and which avoids modifying files imported
from upstream:
sed -ri '
s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g
s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g
' \
$(find $(git ls-files) -prune -type f \
! -name '*.po' \
! -name 'ChangeLog*' \
! -path COPYING ! -path COPYING.LIB \
! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \
! -path manual/texinfo.tex ! -path scripts/config.guess \
! -path scripts/config.sub ! -path scripts/install-sh \
! -path scripts/mkinstalldirs ! -path scripts/move-if-change \
! -path INSTALL ! -path locale/programs/charmap-kw.h \
! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \
! '(' -name configure \
-execdir test -f configure.ac -o -f configure.in ';' ')' \
! '(' -name preconfigure \
-execdir test -f preconfigure.ac ';' ')' \
-print)
and then by running 'make dist-prepare' to regenerate files built
from the altered files, and then executing the following to cleanup:
chmod a+x sysdeps/unix/sysv/linux/riscv/configure
# Omit irrelevant whitespace and comment-only changes,
# perhaps from a slightly-different Autoconf version.
git checkout -f \
sysdeps/csky/configure \
sysdeps/hppa/configure \
sysdeps/riscv/configure \
sysdeps/unix/sysv/linux/csky/configure
# Omit changes that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines
git checkout -f \
sysdeps/powerpc/powerpc64/ppc-mcount.S \
sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
# Omit change that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline
git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 13:40:42 +08:00
|
|
|
<https://www.gnu.org/licenses/>. */
|
1998-12-06 08:44:12 +08:00
|
|
|
|
2019-08-30 07:16:37 +08:00
|
|
|
#include <sys/time.h>
|
1998-12-06 08:44:12 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/poll.h>
|
|
|
|
#include <hurd.h>
|
|
|
|
#include <hurd/fd.h>
|
2019-08-30 07:16:37 +08:00
|
|
|
#include <hurd/io_request.h>
|
2023-05-07 04:55:10 +08:00
|
|
|
#include <mach_rpc.h>
|
1998-12-06 08:44:12 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdint.h>
|
2019-08-30 07:16:37 +08:00
|
|
|
#include <limits.h>
|
2019-10-24 22:20:56 +08:00
|
|
|
#include <time.h>
|
2020-06-29 06:41:18 +08:00
|
|
|
#include <sysdep-cancel.h>
|
1998-12-06 08:44:12 +08:00
|
|
|
|
|
|
|
/* All user select types. */
|
|
|
|
#define SELECT_ALL (SELECT_READ | SELECT_WRITE | SELECT_URG)
|
|
|
|
|
|
|
|
/* Used to record that a particular select rpc returned. Must be distinct
|
|
|
|
from SELECT_ALL (which better not have the high bit set). */
|
|
|
|
#define SELECT_RETURNED ((SELECT_ALL << 1) & ~SELECT_ALL)
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
#define SELECT_ERROR (SELECT_RETURNED << 1)
|
1998-12-06 08:44:12 +08:00
|
|
|
|
|
|
|
/* Check the first NFDS descriptors either in POLLFDS (if nonnnull) or in
|
|
|
|
each of READFDS, WRITEFDS, EXCEPTFDS that is nonnull. If TIMEOUT is not
|
|
|
|
NULL, time out after waiting the interval specified therein. Returns
|
|
|
|
the number of ready descriptors, or -1 for errors. */
|
|
|
|
int
|
|
|
|
_hurd_select (int nfds,
|
|
|
|
struct pollfd *pollfds,
|
|
|
|
fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|
|
|
const struct timespec *timeout, const sigset_t *sigmask)
|
|
|
|
{
|
|
|
|
int i;
|
2020-05-28 07:42:24 +08:00
|
|
|
mach_port_t portset, sigport;
|
2019-08-30 07:16:37 +08:00
|
|
|
int got, ready;
|
1998-12-06 08:44:12 +08:00
|
|
|
error_t err;
|
|
|
|
fd_set rfds, wfds, xfds;
|
|
|
|
int firstfd, lastfd;
|
2019-08-30 07:16:37 +08:00
|
|
|
mach_msg_id_t reply_msgid;
|
|
|
|
mach_msg_timeout_t to;
|
|
|
|
struct timespec ts;
|
1998-12-06 08:44:12 +08:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
struct hurd_userlink ulink;
|
|
|
|
struct hurd_fd *cell;
|
|
|
|
mach_port_t io_port;
|
|
|
|
int type;
|
|
|
|
mach_port_t reply_port;
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
int error;
|
1998-12-06 08:44:12 +08:00
|
|
|
} d[nfds];
|
|
|
|
sigset_t oset;
|
2021-08-04 01:37:43 +08:00
|
|
|
struct hurd_sigstate *ss = NULL;
|
1998-12-06 08:44:12 +08:00
|
|
|
|
2015-02-08 05:07:38 +08:00
|
|
|
if (nfds < 0 || (pollfds == NULL && nfds > FD_SETSIZE))
|
2023-05-20 19:55:29 +08:00
|
|
|
return __hurd_fail (EINVAL);
|
2012-05-11 06:32:53 +08:00
|
|
|
|
2019-08-30 07:16:37 +08:00
|
|
|
#define IO_SELECT_REPLY_MSGID (21012 + 100) /* XXX */
|
|
|
|
#define IO_SELECT_TIMEOUT_REPLY_MSGID (21031 + 100) /* XXX */
|
|
|
|
|
|
|
|
if (timeout == NULL)
|
|
|
|
reply_msgid = IO_SELECT_REPLY_MSGID;
|
|
|
|
else
|
2012-05-11 06:32:53 +08:00
|
|
|
{
|
2019-11-07 16:52:11 +08:00
|
|
|
struct timespec now;
|
2019-08-30 07:16:37 +08:00
|
|
|
|
2019-10-24 22:20:56 +08:00
|
|
|
if (timeout->tv_sec < 0 || ! valid_nanoseconds (timeout->tv_nsec))
|
2023-05-20 19:55:29 +08:00
|
|
|
return __hurd_fail (EINVAL);
|
2012-05-11 06:32:53 +08:00
|
|
|
|
2019-11-07 16:52:11 +08:00
|
|
|
err = __clock_gettime (CLOCK_REALTIME, &now);
|
2019-08-30 07:16:37 +08:00
|
|
|
if (err)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
ts.tv_sec = now.tv_sec + timeout->tv_sec;
|
2019-11-07 16:52:11 +08:00
|
|
|
ts.tv_nsec = now.tv_nsec + timeout->tv_nsec;
|
2019-08-30 07:16:37 +08:00
|
|
|
|
|
|
|
if (ts.tv_nsec >= 1000000000)
|
|
|
|
{
|
|
|
|
ts.tv_sec++;
|
|
|
|
ts.tv_nsec -= 1000000000;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ts.tv_sec < 0)
|
|
|
|
ts.tv_sec = LONG_MAX; /* XXX */
|
|
|
|
|
|
|
|
reply_msgid = IO_SELECT_TIMEOUT_REPLY_MSGID;
|
2012-05-11 06:32:53 +08:00
|
|
|
}
|
|
|
|
|
2020-05-28 07:42:24 +08:00
|
|
|
if (sigmask)
|
|
|
|
{
|
|
|
|
/* Add a port to the portset for the case when we get the signal even
|
|
|
|
before calling __mach_msg. */
|
|
|
|
|
|
|
|
sigport = __mach_reply_port ();
|
|
|
|
|
|
|
|
ss = _hurd_self_sigstate ();
|
|
|
|
_hurd_sigstate_lock (ss);
|
|
|
|
/* And tell the signal thread to message us when a signal arrives. */
|
|
|
|
ss->suspended = sigport;
|
|
|
|
_hurd_sigstate_unlock (ss);
|
|
|
|
|
|
|
|
if (__sigprocmask (SIG_SETMASK, sigmask, &oset))
|
|
|
|
{
|
|
|
|
_hurd_sigstate_lock (ss);
|
|
|
|
ss->suspended = MACH_PORT_NULL;
|
|
|
|
_hurd_sigstate_unlock (ss);
|
|
|
|
__mach_port_destroy (__mach_task_self (), sigport);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
sigport = MACH_PORT_NULL;
|
1998-12-06 08:44:12 +08:00
|
|
|
|
|
|
|
if (pollfds)
|
|
|
|
{
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
int error = 0;
|
1998-12-06 08:44:12 +08:00
|
|
|
/* Collect interesting descriptors from the user's `pollfd' array.
|
|
|
|
We do a first pass that reads the user's array before taking
|
|
|
|
any locks. The second pass then only touches our own stack,
|
|
|
|
and gets the port references. */
|
|
|
|
|
|
|
|
for (i = 0; i < nfds; ++i)
|
|
|
|
if (pollfds[i].fd >= 0)
|
|
|
|
{
|
|
|
|
int type = 0;
|
|
|
|
if (pollfds[i].events & POLLIN)
|
|
|
|
type |= SELECT_READ;
|
|
|
|
if (pollfds[i].events & POLLOUT)
|
|
|
|
type |= SELECT_WRITE;
|
|
|
|
if (pollfds[i].events & POLLPRI)
|
|
|
|
type |= SELECT_URG;
|
|
|
|
|
|
|
|
d[i].io_port = pollfds[i].fd;
|
|
|
|
d[i].type = type;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
d[i].type = 0;
|
|
|
|
|
|
|
|
HURD_CRITICAL_BEGIN;
|
|
|
|
__mutex_lock (&_hurd_dtable_lock);
|
|
|
|
|
|
|
|
for (i = 0; i < nfds; ++i)
|
|
|
|
if (d[i].type != 0)
|
|
|
|
{
|
|
|
|
const int fd = (int) d[i].io_port;
|
|
|
|
|
|
|
|
if (fd < _hurd_dtablesize)
|
|
|
|
{
|
|
|
|
d[i].cell = _hurd_dtable[fd];
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
if (d[i].cell != NULL)
|
|
|
|
{
|
|
|
|
d[i].io_port = _hurd_port_get (&d[i].cell->port,
|
|
|
|
&d[i].ulink);
|
|
|
|
if (d[i].io_port != MACH_PORT_NULL)
|
|
|
|
continue;
|
|
|
|
}
|
1998-12-06 08:44:12 +08:00
|
|
|
}
|
|
|
|
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
/* Bogus descriptor, make it EBADF already. */
|
|
|
|
d[i].error = EBADF;
|
|
|
|
d[i].type = SELECT_ERROR;
|
|
|
|
error = 1;
|
1998-12-06 08:44:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
__mutex_unlock (&_hurd_dtable_lock);
|
|
|
|
HURD_CRITICAL_END;
|
|
|
|
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
if (error)
|
1998-12-06 08:44:12 +08:00
|
|
|
{
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
/* Set timeout to 0. */
|
2019-11-07 16:52:11 +08:00
|
|
|
err = __clock_gettime (CLOCK_REALTIME, &ts);
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
/* Really bad luck. */
|
|
|
|
err = errno;
|
|
|
|
HURD_CRITICAL_BEGIN;
|
|
|
|
__mutex_lock (&_hurd_dtable_lock);
|
|
|
|
while (i-- > 0)
|
|
|
|
if (d[i].type & ~SELECT_ERROR != 0)
|
|
|
|
_hurd_port_free (&d[i].cell->port, &d[i].ulink,
|
|
|
|
d[i].io_port);
|
|
|
|
__mutex_unlock (&_hurd_dtable_lock);
|
|
|
|
HURD_CRITICAL_END;
|
2020-05-28 07:42:24 +08:00
|
|
|
if (sigmask)
|
|
|
|
__sigprocmask (SIG_SETMASK, &oset, NULL);
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
errno = err;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
reply_msgid = IO_SELECT_TIMEOUT_REPLY_MSGID;
|
1998-12-06 08:44:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
lastfd = i - 1;
|
|
|
|
firstfd = i == 0 ? lastfd : 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Collect interested descriptors from the user's fd_set arguments.
|
|
|
|
Use local copies so we can't crash from user bogosity. */
|
|
|
|
|
|
|
|
if (readfds == NULL)
|
|
|
|
FD_ZERO (&rfds);
|
|
|
|
else
|
|
|
|
rfds = *readfds;
|
|
|
|
if (writefds == NULL)
|
|
|
|
FD_ZERO (&wfds);
|
|
|
|
else
|
|
|
|
wfds = *writefds;
|
|
|
|
if (exceptfds == NULL)
|
|
|
|
FD_ZERO (&xfds);
|
|
|
|
else
|
|
|
|
xfds = *exceptfds;
|
|
|
|
|
|
|
|
HURD_CRITICAL_BEGIN;
|
|
|
|
__mutex_lock (&_hurd_dtable_lock);
|
|
|
|
|
|
|
|
/* Collect the ports for interesting FDs. */
|
|
|
|
firstfd = lastfd = -1;
|
|
|
|
for (i = 0; i < nfds; ++i)
|
|
|
|
{
|
|
|
|
int type = 0;
|
|
|
|
if (readfds != NULL && FD_ISSET (i, &rfds))
|
|
|
|
type |= SELECT_READ;
|
|
|
|
if (writefds != NULL && FD_ISSET (i, &wfds))
|
|
|
|
type |= SELECT_WRITE;
|
|
|
|
if (exceptfds != NULL && FD_ISSET (i, &xfds))
|
|
|
|
type |= SELECT_URG;
|
|
|
|
d[i].type = type;
|
|
|
|
if (type)
|
|
|
|
{
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
if (i < _hurd_dtablesize)
|
|
|
|
{
|
|
|
|
d[i].cell = _hurd_dtable[i];
|
|
|
|
if (d[i].cell != NULL)
|
|
|
|
d[i].io_port = _hurd_port_get (&d[i].cell->port,
|
|
|
|
&d[i].ulink);
|
|
|
|
}
|
|
|
|
if (i >= _hurd_dtablesize || d[i].cell == NULL ||
|
|
|
|
d[i].io_port == MACH_PORT_NULL)
|
1998-12-06 08:44:12 +08:00
|
|
|
{
|
|
|
|
/* If one descriptor is bogus, we fail completely. */
|
|
|
|
while (i-- > 0)
|
1999-02-27 21:27:03 +08:00
|
|
|
if (d[i].type != 0)
|
|
|
|
_hurd_port_free (&d[i].cell->port, &d[i].ulink,
|
|
|
|
d[i].io_port);
|
1998-12-06 08:44:12 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
lastfd = i;
|
|
|
|
if (firstfd == -1)
|
|
|
|
firstfd = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
__mutex_unlock (&_hurd_dtable_lock);
|
|
|
|
HURD_CRITICAL_END;
|
|
|
|
|
|
|
|
if (i < nfds)
|
|
|
|
{
|
|
|
|
if (sigmask)
|
|
|
|
__sigprocmask (SIG_SETMASK, &oset, NULL);
|
2023-05-20 19:55:29 +08:00
|
|
|
return __hurd_fail (EBADF);
|
1998-12-06 08:44:12 +08:00
|
|
|
}
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
|
|
|
|
if (nfds > _hurd_dtablesize)
|
|
|
|
nfds = _hurd_dtablesize;
|
1998-12-06 08:44:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
err = 0;
|
|
|
|
got = 0;
|
|
|
|
|
|
|
|
/* Send them all io_select request messages. */
|
|
|
|
|
|
|
|
if (firstfd == -1)
|
2020-05-28 07:42:24 +08:00
|
|
|
{
|
|
|
|
if (sigport == MACH_PORT_NULL)
|
|
|
|
/* But not if there were no ports to deal with at all.
|
|
|
|
We are just a pure timeout. */
|
|
|
|
portset = __mach_reply_port ();
|
|
|
|
else
|
|
|
|
portset = sigport;
|
|
|
|
}
|
1998-12-06 08:44:12 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
portset = MACH_PORT_NULL;
|
|
|
|
|
|
|
|
for (i = firstfd; i <= lastfd; ++i)
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
if (!(d[i].type & ~SELECT_ERROR))
|
|
|
|
d[i].reply_port = MACH_PORT_NULL;
|
|
|
|
else
|
1998-12-06 08:44:12 +08:00
|
|
|
{
|
|
|
|
int type = d[i].type;
|
|
|
|
d[i].reply_port = __mach_reply_port ();
|
2019-08-30 07:16:37 +08:00
|
|
|
if (timeout == NULL)
|
|
|
|
err = __io_select_request (d[i].io_port, d[i].reply_port, type);
|
|
|
|
else
|
|
|
|
err = __io_select_timeout_request (d[i].io_port, d[i].reply_port,
|
|
|
|
ts, type);
|
|
|
|
if (!err)
|
1998-12-06 08:44:12 +08:00
|
|
|
{
|
2020-05-28 07:42:24 +08:00
|
|
|
if (firstfd == lastfd && sigport == MACH_PORT_NULL)
|
1998-12-06 08:44:12 +08:00
|
|
|
/* When there's a single descriptor, we don't need a
|
|
|
|
portset, so just pretend we have one, but really
|
|
|
|
use the single reply port. */
|
|
|
|
portset = d[i].reply_port;
|
|
|
|
else if (got == 0)
|
|
|
|
/* We've got multiple reply ports, so we need a port set to
|
|
|
|
multiplex them. */
|
|
|
|
{
|
|
|
|
/* We will wait again for a reply later. */
|
|
|
|
if (portset == MACH_PORT_NULL)
|
|
|
|
/* Create the portset to receive all the replies on. */
|
|
|
|
err = __mach_port_allocate (__mach_task_self (),
|
|
|
|
MACH_PORT_RIGHT_PORT_SET,
|
|
|
|
&portset);
|
|
|
|
if (! err)
|
|
|
|
/* Put this reply port in the port set. */
|
|
|
|
__mach_port_move_member (__mach_task_self (),
|
|
|
|
d[i].reply_port, portset);
|
|
|
|
}
|
2019-08-30 07:16:37 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
/* No error should happen, but record it for later
|
|
|
|
processing. */
|
|
|
|
d[i].error = err;
|
|
|
|
d[i].type |= SELECT_ERROR;
|
1998-12-06 08:44:12 +08:00
|
|
|
++got;
|
|
|
|
}
|
|
|
|
_hurd_port_free (&d[i].cell->port, &d[i].ulink, d[i].io_port);
|
|
|
|
}
|
2020-05-28 07:42:24 +08:00
|
|
|
|
|
|
|
if (got == 0 && sigport != MACH_PORT_NULL)
|
|
|
|
{
|
|
|
|
if (portset == MACH_PORT_NULL)
|
|
|
|
/* Create the portset to receive the signal message on. */
|
|
|
|
__mach_port_allocate (__mach_task_self (), MACH_PORT_RIGHT_PORT_SET,
|
|
|
|
&portset);
|
|
|
|
/* Put the signal reply port in the port set. */
|
|
|
|
__mach_port_move_member (__mach_task_self (), sigport, portset);
|
|
|
|
}
|
1998-12-06 08:44:12 +08:00
|
|
|
}
|
|
|
|
|
2019-08-30 07:16:37 +08:00
|
|
|
/* GOT is the number of replies (or errors), while READY is the number of
|
|
|
|
replies with at least one type bit set. */
|
|
|
|
ready = 0;
|
|
|
|
|
1998-12-06 08:44:12 +08:00
|
|
|
/* Now wait for reply messages. */
|
|
|
|
if (!err && got == 0)
|
|
|
|
{
|
|
|
|
/* Now wait for io_select_reply messages on PORT,
|
|
|
|
timing out as appropriate. */
|
|
|
|
|
|
|
|
union
|
|
|
|
{
|
|
|
|
mach_msg_header_t head;
|
2002-02-18 06:54:39 +08:00
|
|
|
#ifdef MACH_MSG_TRAILER_MINIMUM_SIZE
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
mach_msg_header_t head;
|
|
|
|
NDR_record_t ndr;
|
|
|
|
error_t err;
|
|
|
|
} error;
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
mach_msg_header_t head;
|
|
|
|
NDR_record_t ndr;
|
|
|
|
error_t err;
|
|
|
|
int result;
|
|
|
|
mach_msg_trailer_t trailer;
|
|
|
|
} success;
|
|
|
|
#else
|
1998-12-06 08:44:12 +08:00
|
|
|
struct
|
|
|
|
{
|
|
|
|
mach_msg_header_t head;
|
2023-05-07 04:55:10 +08:00
|
|
|
mach_msg_type_t err_type;
|
1998-12-06 08:44:12 +08:00
|
|
|
error_t err;
|
|
|
|
} error;
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
mach_msg_header_t head;
|
2023-05-07 04:55:10 +08:00
|
|
|
mach_msg_type_t err_type;
|
1998-12-06 08:44:12 +08:00
|
|
|
error_t err;
|
2023-05-07 04:55:10 +08:00
|
|
|
mach_msg_type_t result_type;
|
1998-12-06 08:44:12 +08:00
|
|
|
int result;
|
|
|
|
} success;
|
2002-02-18 06:54:39 +08:00
|
|
|
#endif
|
1998-12-06 08:44:12 +08:00
|
|
|
} msg;
|
2019-08-30 07:16:37 +08:00
|
|
|
mach_msg_option_t options;
|
1998-12-06 08:44:12 +08:00
|
|
|
error_t msgerr;
|
2019-08-30 07:16:37 +08:00
|
|
|
|
|
|
|
/* We rely on servers to implement the timeout, but when there are none,
|
|
|
|
do it on the client side. */
|
|
|
|
if (timeout != NULL && firstfd == -1)
|
|
|
|
{
|
|
|
|
options = MACH_RCV_TIMEOUT;
|
|
|
|
to = timeout->tv_sec * 1000 + (timeout->tv_nsec + 999999) / 1000000;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
options = 0;
|
|
|
|
to = MACH_MSG_TIMEOUT_NONE;
|
|
|
|
}
|
|
|
|
|
2020-06-29 06:41:18 +08:00
|
|
|
int cancel_oldtype = LIBC_CANCEL_ASYNC();
|
1998-12-06 08:44:12 +08:00
|
|
|
while ((msgerr = __mach_msg (&msg.head,
|
2015-02-08 05:13:46 +08:00
|
|
|
MACH_RCV_MSG | MACH_RCV_INTERRUPT | options,
|
1998-12-06 08:44:12 +08:00
|
|
|
0, sizeof msg, portset, to,
|
|
|
|
MACH_PORT_NULL)) == MACH_MSG_SUCCESS)
|
|
|
|
{
|
2020-06-29 06:41:18 +08:00
|
|
|
LIBC_CANCEL_RESET (cancel_oldtype);
|
|
|
|
|
1998-12-06 08:44:12 +08:00
|
|
|
/* We got a message. Decode it. */
|
2002-02-18 06:54:39 +08:00
|
|
|
#ifdef MACH_MSG_TYPE_BIT
|
2023-05-07 04:55:10 +08:00
|
|
|
static const mach_msg_type_t inttype = {
|
|
|
|
.msgt_name = MACH_MSG_TYPE_INTEGER_T,
|
|
|
|
.msgt_size = sizeof (integer_t) * 8,
|
|
|
|
.msgt_number = 1,
|
|
|
|
.msgt_inline = TRUE,
|
|
|
|
.msgt_longform = FALSE,
|
|
|
|
.msgt_deallocate = FALSE,
|
|
|
|
.msgt_unused = 0
|
2002-04-02 12:43:06 +08:00
|
|
|
};
|
2002-02-18 06:54:39 +08:00
|
|
|
#endif
|
2020-05-28 07:42:24 +08:00
|
|
|
|
|
|
|
if (sigport != MACH_PORT_NULL && sigport == msg.head.msgh_local_port)
|
|
|
|
{
|
|
|
|
/* We actually got interrupted by a signal before
|
|
|
|
__mach_msg; poll for further responses and then
|
|
|
|
return quickly. */
|
|
|
|
err = EINTR;
|
|
|
|
goto poll;
|
|
|
|
}
|
|
|
|
|
2019-08-30 07:16:37 +08:00
|
|
|
if (msg.head.msgh_id == reply_msgid
|
Break some lines before not after operators.
The GNU Coding Standards specify that line breaks in expressions
should go before an operator, not after one. This patch fixes various
code to do this. It only changes code that appears to be mostly
following GNU style anyway, not files and directories with
substantially different formatting. It is not exhaustive even for
files using GNU style (for example, changes to sysdeps files are
deferred for subsequent cleanups). Some files changed are shared with
gnulib, but most are specific to glibc. Changes were made manually,
with places to change found by grep (so some cases, e.g. where the
operator was followed by a comment at end of line, are particularly
liable to have been missed by grep, but I did include cases where the
operator was followed by backslash-newline).
This patch generally does not attempt to address other coding style
issues in the expressions changed (for example, missing spaces before
'(', or lack of parentheses to ensure indentation of continuation
lines properly reflects operator precedence).
Tested for x86_64, and with build-many-glibcs.py.
* benchtests/bench-memmem.c (simple_memmem): Break lines before
rather than after operators.
* benchtests/bench-skeleton.c (TIMESPEC_AFTER): Likewise.
* crypt/md5.c (md5_finish_ctx): Likewise.
* crypt/sha256.c (__sha256_finish_ctx): Likewise.
* crypt/sha512.c (__sha512_finish_ctx): Likewise.
* elf/cache.c (load_aux_cache): Likewise.
* elf/dl-load.c (open_verify): Likewise.
* elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise.
* elf/readelflib.c (process_elf_file): Likewise.
* elf/rtld.c (dl_main): Likewise.
* elf/sprof.c (generate_call_graph): Likewise.
* hurd/ctty-input.c (_hurd_ctty_input): Likewise.
* hurd/ctty-output.c (_hurd_ctty_output): Likewise.
* hurd/dtable.c (reauth_dtable): Likewise.
* hurd/getdport.c (__getdport): Likewise.
* hurd/hurd/signal.h (_hurd_interrupted_rpc_timeout): Likewise.
* hurd/hurd/sigpreempt.h (HURD_PREEMPT_SIGNAL_P): Likewise.
* hurd/hurdfault.c (_hurdsig_fault_catch_exception_raise):
Likewise.
* hurd/hurdioctl.c (fioctl): Likewise.
* hurd/hurdselect.c (_hurd_select): Likewise.
* hurd/hurdsig.c (_hurdsig_abort_rpcs): Likewise.
(STOPSIGS): Likewise.
* hurd/hurdstartup.c (_hurd_startup): Likewise.
* hurd/intr-msg.c (_hurd_intr_rpc_mach_msg): Likewise.
* hurd/lookup-retry.c (__hurd_file_name_lookup_retry): Likewise.
* hurd/msgportdemux.c (msgport_server): Likewise.
* hurd/setauth.c (_hurd_setauth): Likewise.
* include/features.h (__GLIBC_USE_DEPRECATED_SCANF): Likewise.
* libio/libioP.h [IO_DEBUG] (CHECK_FILE): Likewise.
* locale/programs/ld-ctype.c (set_class_defaults): Likewise.
* localedata/tests-mbwc/tst_swscanf.c (tst_swscanf): Likewise.
* login/tst-utmp.c (do_check): Likewise.
(simulate_login): Likewise.
* mach/lowlevellock.h (lll_lock): Likewise.
(lll_trylock): Likewise.
* math/test-fenv.c (ALL_EXC): Likewise.
* math/test-fenvinline.c (ALL_EXC): Likewise.
* misc/sys/cdefs.h (__attribute_deprecated_msg__): Likewise.
* nis/nis_call.c (__do_niscall3): Likewise.
* nis/nis_callback.c (cb_prog_1): Likewise.
* nis/nis_defaults.c (searchaccess): Likewise.
* nis/nis_findserv.c (__nis_findfastest_with_timeout): Likewise.
* nis/nis_ismember.c (internal_ismember): Likewise.
* nis/nis_local_names.c (nis_local_principal): Likewise.
* nis/nss_nis/nis-rpc.c (_nss_nis_getrpcbyname_r): Likewise.
* nis/nss_nisplus/nisplus-netgrp.c (_nss_nisplus_getnetgrent_r):
Likewise.
* nis/ypclnt.c (yp_match): Likewise.
(yp_first): Likewise.
(yp_next): Likewise.
(yp_master): Likewise.
(yp_order): Likewise.
* nscd/hstcache.c (cache_addhst): Likewise.
* nscd/initgrcache.c (addinitgroupsX): Likewise.
* nss/nss_compat/compat-pwd.c (copy_pwd_changes): Likewise.
(internal_getpwuid_r): Likewise.
* nss/nss_compat/compat-spwd.c (copy_spwd_changes): Likewise.
* posix/glob.h (__GLOB_FLAGS): Likewise.
* posix/regcomp.c (peek_token): Likewise.
(peek_token_bracket): Likewise.
(parse_expression): Likewise.
* posix/regexec.c (sift_states_iter_mb): Likewise.
(check_node_accept_bytes): Likewise.
* posix/tst-spawn3.c (do_test): Likewise.
* posix/wordexp-test.c (testit): Likewise.
* posix/wordexp.c (parse_tilde): Likewise.
(exec_comm): Likewise.
* posix/wordexp.h (__WRDE_FLAGS): Likewise.
* resource/vtimes.c (TIMEVAL_TO_VTIMES): Likewise.
* setjmp/sigjmp.c (__sigjmp_save): Likewise.
* stdio-common/printf_fp.c (__printf_fp_l): Likewise.
* stdio-common/tst-fileno.c (do_test): Likewise.
* stdio-common/vfprintf-internal.c (vfprintf): Likewise.
* stdlib/strfmon_l.c (__vstrfmon_l_internal): Likewise.
* stdlib/strtod_l.c (round_and_return): Likewise.
(____STRTOF_INTERNAL): Likewise.
* stdlib/tst-strfrom.h (TEST_STRFROM): Likewise.
* string/strcspn.c (STRCSPN): Likewise.
* string/test-memmem.c (simple_memmem): Likewise.
* termios/tcsetattr.c (tcsetattr): Likewise.
* time/alt_digit.c (_nl_parse_alt_digit): Likewise.
* time/asctime.c (asctime_internal): Likewise.
* time/strptime_l.c (__strptime_internal): Likewise.
* time/sys/time.h (timercmp): Likewise.
* time/tzfile.c (__tzfile_compute): Likewise.
2019-02-22 09:32:36 +08:00
|
|
|
&& msg.head.msgh_size >= sizeof msg.error
|
|
|
|
&& !(msg.head.msgh_bits & MACH_MSGH_BITS_COMPLEX)
|
2002-02-18 06:54:39 +08:00
|
|
|
#ifdef MACH_MSG_TYPE_BIT
|
2023-05-07 04:55:10 +08:00
|
|
|
&& !BAD_TYPECHECK (&msg.error.err_type, &inttype)
|
2002-02-18 06:54:39 +08:00
|
|
|
#endif
|
|
|
|
)
|
1998-12-06 08:44:12 +08:00
|
|
|
{
|
|
|
|
/* This is a properly formatted message so far.
|
|
|
|
See if it is a success or a failure. */
|
Break some lines before not after operators.
The GNU Coding Standards specify that line breaks in expressions
should go before an operator, not after one. This patch fixes various
code to do this. It only changes code that appears to be mostly
following GNU style anyway, not files and directories with
substantially different formatting. It is not exhaustive even for
files using GNU style (for example, changes to sysdeps files are
deferred for subsequent cleanups). Some files changed are shared with
gnulib, but most are specific to glibc. Changes were made manually,
with places to change found by grep (so some cases, e.g. where the
operator was followed by a comment at end of line, are particularly
liable to have been missed by grep, but I did include cases where the
operator was followed by backslash-newline).
This patch generally does not attempt to address other coding style
issues in the expressions changed (for example, missing spaces before
'(', or lack of parentheses to ensure indentation of continuation
lines properly reflects operator precedence).
Tested for x86_64, and with build-many-glibcs.py.
* benchtests/bench-memmem.c (simple_memmem): Break lines before
rather than after operators.
* benchtests/bench-skeleton.c (TIMESPEC_AFTER): Likewise.
* crypt/md5.c (md5_finish_ctx): Likewise.
* crypt/sha256.c (__sha256_finish_ctx): Likewise.
* crypt/sha512.c (__sha512_finish_ctx): Likewise.
* elf/cache.c (load_aux_cache): Likewise.
* elf/dl-load.c (open_verify): Likewise.
* elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise.
* elf/readelflib.c (process_elf_file): Likewise.
* elf/rtld.c (dl_main): Likewise.
* elf/sprof.c (generate_call_graph): Likewise.
* hurd/ctty-input.c (_hurd_ctty_input): Likewise.
* hurd/ctty-output.c (_hurd_ctty_output): Likewise.
* hurd/dtable.c (reauth_dtable): Likewise.
* hurd/getdport.c (__getdport): Likewise.
* hurd/hurd/signal.h (_hurd_interrupted_rpc_timeout): Likewise.
* hurd/hurd/sigpreempt.h (HURD_PREEMPT_SIGNAL_P): Likewise.
* hurd/hurdfault.c (_hurdsig_fault_catch_exception_raise):
Likewise.
* hurd/hurdioctl.c (fioctl): Likewise.
* hurd/hurdselect.c (_hurd_select): Likewise.
* hurd/hurdsig.c (_hurdsig_abort_rpcs): Likewise.
(STOPSIGS): Likewise.
* hurd/hurdstartup.c (_hurd_startup): Likewise.
* hurd/intr-msg.c (_hurd_intr_rpc_mach_msg): Likewise.
* hurd/lookup-retry.c (__hurd_file_name_lookup_retry): Likewise.
* hurd/msgportdemux.c (msgport_server): Likewise.
* hurd/setauth.c (_hurd_setauth): Likewise.
* include/features.h (__GLIBC_USE_DEPRECATED_SCANF): Likewise.
* libio/libioP.h [IO_DEBUG] (CHECK_FILE): Likewise.
* locale/programs/ld-ctype.c (set_class_defaults): Likewise.
* localedata/tests-mbwc/tst_swscanf.c (tst_swscanf): Likewise.
* login/tst-utmp.c (do_check): Likewise.
(simulate_login): Likewise.
* mach/lowlevellock.h (lll_lock): Likewise.
(lll_trylock): Likewise.
* math/test-fenv.c (ALL_EXC): Likewise.
* math/test-fenvinline.c (ALL_EXC): Likewise.
* misc/sys/cdefs.h (__attribute_deprecated_msg__): Likewise.
* nis/nis_call.c (__do_niscall3): Likewise.
* nis/nis_callback.c (cb_prog_1): Likewise.
* nis/nis_defaults.c (searchaccess): Likewise.
* nis/nis_findserv.c (__nis_findfastest_with_timeout): Likewise.
* nis/nis_ismember.c (internal_ismember): Likewise.
* nis/nis_local_names.c (nis_local_principal): Likewise.
* nis/nss_nis/nis-rpc.c (_nss_nis_getrpcbyname_r): Likewise.
* nis/nss_nisplus/nisplus-netgrp.c (_nss_nisplus_getnetgrent_r):
Likewise.
* nis/ypclnt.c (yp_match): Likewise.
(yp_first): Likewise.
(yp_next): Likewise.
(yp_master): Likewise.
(yp_order): Likewise.
* nscd/hstcache.c (cache_addhst): Likewise.
* nscd/initgrcache.c (addinitgroupsX): Likewise.
* nss/nss_compat/compat-pwd.c (copy_pwd_changes): Likewise.
(internal_getpwuid_r): Likewise.
* nss/nss_compat/compat-spwd.c (copy_spwd_changes): Likewise.
* posix/glob.h (__GLOB_FLAGS): Likewise.
* posix/regcomp.c (peek_token): Likewise.
(peek_token_bracket): Likewise.
(parse_expression): Likewise.
* posix/regexec.c (sift_states_iter_mb): Likewise.
(check_node_accept_bytes): Likewise.
* posix/tst-spawn3.c (do_test): Likewise.
* posix/wordexp-test.c (testit): Likewise.
* posix/wordexp.c (parse_tilde): Likewise.
(exec_comm): Likewise.
* posix/wordexp.h (__WRDE_FLAGS): Likewise.
* resource/vtimes.c (TIMEVAL_TO_VTIMES): Likewise.
* setjmp/sigjmp.c (__sigjmp_save): Likewise.
* stdio-common/printf_fp.c (__printf_fp_l): Likewise.
* stdio-common/tst-fileno.c (do_test): Likewise.
* stdio-common/vfprintf-internal.c (vfprintf): Likewise.
* stdlib/strfmon_l.c (__vstrfmon_l_internal): Likewise.
* stdlib/strtod_l.c (round_and_return): Likewise.
(____STRTOF_INTERNAL): Likewise.
* stdlib/tst-strfrom.h (TEST_STRFROM): Likewise.
* string/strcspn.c (STRCSPN): Likewise.
* string/test-memmem.c (simple_memmem): Likewise.
* termios/tcsetattr.c (tcsetattr): Likewise.
* time/alt_digit.c (_nl_parse_alt_digit): Likewise.
* time/asctime.c (asctime_internal): Likewise.
* time/strptime_l.c (__strptime_internal): Likewise.
* time/sys/time.h (timercmp): Likewise.
* time/tzfile.c (__tzfile_compute): Likewise.
2019-02-22 09:32:36 +08:00
|
|
|
if (msg.error.err == EINTR
|
|
|
|
&& msg.head.msgh_size == sizeof msg.error)
|
1998-12-06 08:44:12 +08:00
|
|
|
{
|
|
|
|
/* EINTR response; poll for further responses
|
|
|
|
and then return quickly. */
|
|
|
|
err = EINTR;
|
|
|
|
goto poll;
|
|
|
|
}
|
2019-08-30 07:16:37 +08:00
|
|
|
/* Keep in mind msg.success.result can be 0 if a timeout
|
|
|
|
occurred. */
|
Break some lines before not after operators.
The GNU Coding Standards specify that line breaks in expressions
should go before an operator, not after one. This patch fixes various
code to do this. It only changes code that appears to be mostly
following GNU style anyway, not files and directories with
substantially different formatting. It is not exhaustive even for
files using GNU style (for example, changes to sysdeps files are
deferred for subsequent cleanups). Some files changed are shared with
gnulib, but most are specific to glibc. Changes were made manually,
with places to change found by grep (so some cases, e.g. where the
operator was followed by a comment at end of line, are particularly
liable to have been missed by grep, but I did include cases where the
operator was followed by backslash-newline).
This patch generally does not attempt to address other coding style
issues in the expressions changed (for example, missing spaces before
'(', or lack of parentheses to ensure indentation of continuation
lines properly reflects operator precedence).
Tested for x86_64, and with build-many-glibcs.py.
* benchtests/bench-memmem.c (simple_memmem): Break lines before
rather than after operators.
* benchtests/bench-skeleton.c (TIMESPEC_AFTER): Likewise.
* crypt/md5.c (md5_finish_ctx): Likewise.
* crypt/sha256.c (__sha256_finish_ctx): Likewise.
* crypt/sha512.c (__sha512_finish_ctx): Likewise.
* elf/cache.c (load_aux_cache): Likewise.
* elf/dl-load.c (open_verify): Likewise.
* elf/get-dynamic-info.h (elf_get_dynamic_info): Likewise.
* elf/readelflib.c (process_elf_file): Likewise.
* elf/rtld.c (dl_main): Likewise.
* elf/sprof.c (generate_call_graph): Likewise.
* hurd/ctty-input.c (_hurd_ctty_input): Likewise.
* hurd/ctty-output.c (_hurd_ctty_output): Likewise.
* hurd/dtable.c (reauth_dtable): Likewise.
* hurd/getdport.c (__getdport): Likewise.
* hurd/hurd/signal.h (_hurd_interrupted_rpc_timeout): Likewise.
* hurd/hurd/sigpreempt.h (HURD_PREEMPT_SIGNAL_P): Likewise.
* hurd/hurdfault.c (_hurdsig_fault_catch_exception_raise):
Likewise.
* hurd/hurdioctl.c (fioctl): Likewise.
* hurd/hurdselect.c (_hurd_select): Likewise.
* hurd/hurdsig.c (_hurdsig_abort_rpcs): Likewise.
(STOPSIGS): Likewise.
* hurd/hurdstartup.c (_hurd_startup): Likewise.
* hurd/intr-msg.c (_hurd_intr_rpc_mach_msg): Likewise.
* hurd/lookup-retry.c (__hurd_file_name_lookup_retry): Likewise.
* hurd/msgportdemux.c (msgport_server): Likewise.
* hurd/setauth.c (_hurd_setauth): Likewise.
* include/features.h (__GLIBC_USE_DEPRECATED_SCANF): Likewise.
* libio/libioP.h [IO_DEBUG] (CHECK_FILE): Likewise.
* locale/programs/ld-ctype.c (set_class_defaults): Likewise.
* localedata/tests-mbwc/tst_swscanf.c (tst_swscanf): Likewise.
* login/tst-utmp.c (do_check): Likewise.
(simulate_login): Likewise.
* mach/lowlevellock.h (lll_lock): Likewise.
(lll_trylock): Likewise.
* math/test-fenv.c (ALL_EXC): Likewise.
* math/test-fenvinline.c (ALL_EXC): Likewise.
* misc/sys/cdefs.h (__attribute_deprecated_msg__): Likewise.
* nis/nis_call.c (__do_niscall3): Likewise.
* nis/nis_callback.c (cb_prog_1): Likewise.
* nis/nis_defaults.c (searchaccess): Likewise.
* nis/nis_findserv.c (__nis_findfastest_with_timeout): Likewise.
* nis/nis_ismember.c (internal_ismember): Likewise.
* nis/nis_local_names.c (nis_local_principal): Likewise.
* nis/nss_nis/nis-rpc.c (_nss_nis_getrpcbyname_r): Likewise.
* nis/nss_nisplus/nisplus-netgrp.c (_nss_nisplus_getnetgrent_r):
Likewise.
* nis/ypclnt.c (yp_match): Likewise.
(yp_first): Likewise.
(yp_next): Likewise.
(yp_master): Likewise.
(yp_order): Likewise.
* nscd/hstcache.c (cache_addhst): Likewise.
* nscd/initgrcache.c (addinitgroupsX): Likewise.
* nss/nss_compat/compat-pwd.c (copy_pwd_changes): Likewise.
(internal_getpwuid_r): Likewise.
* nss/nss_compat/compat-spwd.c (copy_spwd_changes): Likewise.
* posix/glob.h (__GLOB_FLAGS): Likewise.
* posix/regcomp.c (peek_token): Likewise.
(peek_token_bracket): Likewise.
(parse_expression): Likewise.
* posix/regexec.c (sift_states_iter_mb): Likewise.
(check_node_accept_bytes): Likewise.
* posix/tst-spawn3.c (do_test): Likewise.
* posix/wordexp-test.c (testit): Likewise.
* posix/wordexp.c (parse_tilde): Likewise.
(exec_comm): Likewise.
* posix/wordexp.h (__WRDE_FLAGS): Likewise.
* resource/vtimes.c (TIMEVAL_TO_VTIMES): Likewise.
* setjmp/sigjmp.c (__sigjmp_save): Likewise.
* stdio-common/printf_fp.c (__printf_fp_l): Likewise.
* stdio-common/tst-fileno.c (do_test): Likewise.
* stdio-common/vfprintf-internal.c (vfprintf): Likewise.
* stdlib/strfmon_l.c (__vstrfmon_l_internal): Likewise.
* stdlib/strtod_l.c (round_and_return): Likewise.
(____STRTOF_INTERNAL): Likewise.
* stdlib/tst-strfrom.h (TEST_STRFROM): Likewise.
* string/strcspn.c (STRCSPN): Likewise.
* string/test-memmem.c (simple_memmem): Likewise.
* termios/tcsetattr.c (tcsetattr): Likewise.
* time/alt_digit.c (_nl_parse_alt_digit): Likewise.
* time/asctime.c (asctime_internal): Likewise.
* time/strptime_l.c (__strptime_internal): Likewise.
* time/sys/time.h (timercmp): Likewise.
* time/tzfile.c (__tzfile_compute): Likewise.
2019-02-22 09:32:36 +08:00
|
|
|
if (msg.error.err
|
2002-02-18 06:54:39 +08:00
|
|
|
#ifdef MACH_MSG_TYPE_BIT
|
2023-05-07 04:55:10 +08:00
|
|
|
|| BAD_TYPECHECK (&msg.success.result_type, &inttype)
|
2002-02-18 06:54:39 +08:00
|
|
|
#endif
|
2019-08-30 07:16:37 +08:00
|
|
|
|| msg.head.msgh_size != sizeof msg.success)
|
1998-12-06 08:44:12 +08:00
|
|
|
{
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
/* Error or bogus reply. */
|
|
|
|
if (!msg.error.err)
|
|
|
|
msg.error.err = EIO;
|
1998-12-06 08:44:12 +08:00
|
|
|
__mach_msg_destroy (&msg.head);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Look up the respondent's reply port and record its
|
2012-05-11 06:32:53 +08:00
|
|
|
readiness. */
|
1998-12-06 08:44:12 +08:00
|
|
|
{
|
|
|
|
int had = got;
|
|
|
|
if (firstfd != -1)
|
|
|
|
for (i = firstfd; i <= lastfd; ++i)
|
|
|
|
if (d[i].type
|
|
|
|
&& d[i].reply_port == msg.head.msgh_local_port)
|
|
|
|
{
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
if (msg.error.err)
|
|
|
|
{
|
|
|
|
d[i].error = msg.error.err;
|
|
|
|
d[i].type = SELECT_ERROR;
|
|
|
|
++ready;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d[i].type &= msg.success.result;
|
|
|
|
if (d[i].type)
|
|
|
|
++ready;
|
|
|
|
}
|
2019-08-30 07:16:37 +08:00
|
|
|
|
1998-12-06 08:44:12 +08:00
|
|
|
d[i].type |= SELECT_RETURNED;
|
|
|
|
++got;
|
|
|
|
}
|
|
|
|
assert (got > had);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg.head.msgh_remote_port != MACH_PORT_NULL)
|
|
|
|
__mach_port_deallocate (__mach_task_self (),
|
|
|
|
msg.head.msgh_remote_port);
|
|
|
|
|
|
|
|
if (got)
|
|
|
|
poll:
|
|
|
|
{
|
|
|
|
/* Poll for another message. */
|
|
|
|
to = 0;
|
|
|
|
options |= MACH_RCV_TIMEOUT;
|
|
|
|
}
|
|
|
|
}
|
2020-06-29 06:41:18 +08:00
|
|
|
LIBC_CANCEL_RESET (cancel_oldtype);
|
1998-12-06 08:44:12 +08:00
|
|
|
|
2015-02-08 05:13:46 +08:00
|
|
|
if (msgerr == MACH_RCV_INTERRUPTED)
|
|
|
|
/* Interruption on our side (e.g. signal reception). */
|
|
|
|
err = EINTR;
|
1998-12-06 08:44:12 +08:00
|
|
|
|
2019-08-30 07:16:37 +08:00
|
|
|
if (ready)
|
1998-12-06 08:44:12 +08:00
|
|
|
/* At least one descriptor is known to be ready now, so we will
|
|
|
|
return success. */
|
|
|
|
err = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (firstfd != -1)
|
|
|
|
for (i = firstfd; i <= lastfd; ++i)
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
if (d[i].reply_port != MACH_PORT_NULL)
|
1998-12-06 08:44:12 +08:00
|
|
|
__mach_port_destroy (__mach_task_self (), d[i].reply_port);
|
2020-05-28 07:42:24 +08:00
|
|
|
|
|
|
|
if (sigport != MACH_PORT_NULL)
|
|
|
|
{
|
|
|
|
_hurd_sigstate_lock (ss);
|
|
|
|
ss->suspended = MACH_PORT_NULL;
|
|
|
|
_hurd_sigstate_unlock (ss);
|
|
|
|
__mach_port_destroy (__mach_task_self (), sigport);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((firstfd == -1 && sigport == MACH_PORT_NULL)
|
|
|
|
|| ((firstfd != lastfd || sigport != MACH_PORT_NULL) && portset != MACH_PORT_NULL))
|
1998-12-06 08:44:12 +08:00
|
|
|
/* Destroy PORTSET, but only if it's not actually the reply port for a
|
|
|
|
single descriptor (in which case it's destroyed in the previous loop;
|
|
|
|
not doing it here is just a bit more efficient). */
|
|
|
|
__mach_port_destroy (__mach_task_self (), portset);
|
|
|
|
|
|
|
|
if (err)
|
|
|
|
{
|
|
|
|
if (sigmask)
|
|
|
|
__sigprocmask (SIG_SETMASK, &oset, NULL);
|
|
|
|
return __hurd_fail (err);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pollfds)
|
|
|
|
/* Fill in the `revents' members of the user's array. */
|
|
|
|
for (i = 0; i < nfds; ++i)
|
|
|
|
{
|
2001-10-29 06:10:26 +08:00
|
|
|
int type = d[i].type;
|
2022-04-14 08:46:03 +08:00
|
|
|
int revents = 0;
|
1998-12-06 08:44:12 +08:00
|
|
|
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
if (type & SELECT_ERROR)
|
|
|
|
switch (d[i].error)
|
|
|
|
{
|
|
|
|
case EPIPE:
|
|
|
|
revents = POLLHUP;
|
|
|
|
break;
|
|
|
|
case EBADF:
|
|
|
|
revents = POLLNVAL;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
revents = POLLERR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (type & SELECT_RETURNED)
|
|
|
|
{
|
|
|
|
if (type & SELECT_READ)
|
|
|
|
revents |= POLLIN;
|
|
|
|
if (type & SELECT_WRITE)
|
|
|
|
revents |= POLLOUT;
|
|
|
|
if (type & SELECT_URG)
|
|
|
|
revents |= POLLPRI;
|
|
|
|
}
|
1998-12-06 08:44:12 +08:00
|
|
|
|
|
|
|
pollfds[i].revents = revents;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-08-30 07:16:37 +08:00
|
|
|
/* Below we recalculate READY to include an increment for each operation
|
1998-12-06 08:44:12 +08:00
|
|
|
allowed on each fd. */
|
2019-08-30 07:16:37 +08:00
|
|
|
ready = 0;
|
1998-12-06 08:44:12 +08:00
|
|
|
|
|
|
|
/* Set the user bitarrays. We only ever have to clear bits, as all
|
|
|
|
desired ones are initially set. */
|
|
|
|
if (firstfd != -1)
|
|
|
|
for (i = firstfd; i <= lastfd; ++i)
|
|
|
|
{
|
|
|
|
int type = d[i].type;
|
|
|
|
|
|
|
|
if ((type & SELECT_RETURNED) == 0)
|
|
|
|
type = 0;
|
|
|
|
|
hurd: Fix poll and select POSIX compliancy details about errors
This fixes the following:
- On error, poll must not return without polling, including EBADF, and instead
report POLLHUP/POLLERR/POLLNVAL
- Select must report EBADF if some set contains an invalid FD.
The idea is to move error management to after all select calls, in the
poll/select final treatment. The error is instead recorded in a new `error'
field, and a new SELECT_ERROR bit set.
Thanks Svante Signell for the initial version of the patch.
* hurd/hurdselect.c (SELECT_ERROR): New macro.
(_hurd_select):
- Add `error' field to `d' structures array.
- If a poll descriptor is bogus, set EBADF, but continue with a zero
timeout.
- Go through the whole fd_set, not only until _hurd_dtablesize. Return
EBADF there is any bit set above _hurd_dtablesize.
- Do not request io_select on bogus descriptors (SELECT_ERROR).
- On io_select request error, record the error.
- On io_select bogus reply, use EIO error code.
- On io_select bogus or error reply, record the error.
- Do not destroy reply port for bogus FDs.
- On error, make poll set POLLHUP in the EPIPE case, POLLNVAL in the
EBADF case, or else POLLERR.
- On error, make select simulated readiness.
2019-08-30 07:20:23 +08:00
|
|
|
/* Callers of select don't expect to see errors, so we simulate
|
|
|
|
readiness of the erring object and the next call hopefully
|
|
|
|
will get the error again. */
|
|
|
|
if (type & SELECT_ERROR)
|
|
|
|
{
|
|
|
|
type = 0;
|
|
|
|
if (readfds != NULL && FD_ISSET (i, readfds))
|
|
|
|
type |= SELECT_READ;
|
|
|
|
if (writefds != NULL && FD_ISSET (i, writefds))
|
|
|
|
type |= SELECT_WRITE;
|
|
|
|
if (exceptfds != NULL && FD_ISSET (i, exceptfds))
|
|
|
|
type |= SELECT_URG;
|
|
|
|
}
|
|
|
|
|
1998-12-06 08:44:12 +08:00
|
|
|
if (type & SELECT_READ)
|
2019-08-30 07:16:37 +08:00
|
|
|
ready++;
|
1998-12-06 08:44:12 +08:00
|
|
|
else if (readfds)
|
|
|
|
FD_CLR (i, readfds);
|
|
|
|
if (type & SELECT_WRITE)
|
2019-08-30 07:16:37 +08:00
|
|
|
ready++;
|
1998-12-06 08:44:12 +08:00
|
|
|
else if (writefds)
|
|
|
|
FD_CLR (i, writefds);
|
|
|
|
if (type & SELECT_URG)
|
2019-08-30 07:16:37 +08:00
|
|
|
ready++;
|
1998-12-06 08:44:12 +08:00
|
|
|
else if (exceptfds)
|
|
|
|
FD_CLR (i, exceptfds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sigmask && __sigprocmask (SIG_SETMASK, &oset, NULL))
|
|
|
|
return -1;
|
|
|
|
|
2019-08-30 07:16:37 +08:00
|
|
|
return ready;
|
1998-12-06 08:44:12 +08:00
|
|
|
}
|