posix: Use poll instead, when available, removing use of select.

* configure.ac (HAVE_POLL_H): Add the check.
* src/ath.c [!HAVE_POLL_H] (ath_select): Enable conditionally.
* src/posix-io.c [HAVE_POLL_H] (_gpgme_io_select_poll): Use poll.
* tests/gpg/t-cancel.c [HAVE_POLL_H] (do_select): Use poll.
* tests/gpg/t-eventloop.c [HAVE_POLL_H] (do_select): Use poll.

--

GnuPG-bug-id: 2385
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2021-11-25 11:13:17 +09:00
parent 4583ab77e5
commit 8148237cb4
6 changed files with 269 additions and 16 deletions

View File

@ -538,7 +538,7 @@ AM_CONDITIONAL(RUN_G13_TESTS, test "$run_g13_test" = "yes")
# Checks for header files. # Checks for header files.
AC_CHECK_HEADERS_ONCE([locale.h sys/select.h sys/uio.h argp.h stdint.h AC_CHECK_HEADERS_ONCE([locale.h sys/select.h sys/uio.h argp.h stdint.h
unistd.h sys/time.h sys/types.h sys/stat.h]) unistd.h poll.h sys/time.h sys/types.h sys/stat.h])
# Type checks. # Type checks.

View File

@ -26,12 +26,16 @@
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> # include <unistd.h>
#endif #endif
#ifdef HAVE_SYS_SELECT_H #ifdef HAVE_POLL_H
# include <sys/select.h> # include <poll.h>
#else #else
# ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
# else
# ifdef HAVE_SYS_TIME_H # ifdef HAVE_SYS_TIME_H
# include <sys/time.h> # include <sys/time.h>
# endif # endif
# endif
#endif #endif
#ifdef HAVE_SYS_TYPES_H #ifdef HAVE_SYS_TYPES_H
# include <sys/types.h> # include <sys/types.h>
@ -89,6 +93,7 @@ ath_write (int fd, const void *buf, size_t nbytes)
} }
#if !defined(HAVE_POLL_H)
gpgme_ssize_t gpgme_ssize_t
ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset, ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
struct timeval *timeout) struct timeval *timeout)
@ -99,7 +104,7 @@ ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
return select (nfd, rset, wset, eset, timeout); return select (nfd, rset, wset, eset, timeout);
#endif #endif
} }
#endif
gpgme_ssize_t gpgme_ssize_t
ath_waitpid (pid_t pid, int *status, int options) ath_waitpid (pid_t pid, int *status, int options)

View File

@ -32,7 +32,9 @@
# include <io.h> # include <io.h>
#else /*!HAVE_W32_SYSTEM*/ #else /*!HAVE_W32_SYSTEM*/
# ifdef HAVE_POLL_H
# include <poll.h>
# else
# ifdef HAVE_SYS_SELECT_H # ifdef HAVE_SYS_SELECT_H
# include <sys/select.h> # include <sys/select.h>
# else # else
@ -40,6 +42,7 @@
# include <sys/time.h> # include <sys/time.h>
# endif # endif
# endif # endif
# endif
# ifdef HAVE_SYS_TYPES_H # ifdef HAVE_SYS_TYPES_H
# include <sys/types.h> # include <sys/types.h>
# endif # endif

View File

@ -691,8 +691,119 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
/* Select on the list of fds. Returns: -1 = error, 0 = timeout or /* Select on the list of fds. Returns: -1 = error, 0 = timeout or
nothing to select, > 0 = number of signaled fds. */ nothing to select, > 0 = number of signaled fds. */
int #ifdef HAVE_POLL_H
_gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock) static int
_gpgme_io_select_poll (struct io_select_fd_s *fds, size_t nfds, int nonblock)
{
struct pollfd *poll_fds = NULL;
nfds_t poll_nfds;
/* Use a 1s timeout. */
int timeout = 1000;
unsigned int i;
int any;
int count;
void *dbg_help = NULL;
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_select", NULL,
"nfds=%zu, nonblock=%u", nfds, nonblock);
if (nonblock)
timeout = 0;
poll_fds = malloc (sizeof (*poll_fds)*nfds);
if (!poll_fds)
return -1;
poll_nfds = 0;
TRACE_SEQ (dbg_help, "poll on [ ");
any = 0;
for (i = 0; i < nfds; i++)
{
if (fds[i].fd == -1)
continue;
if (fds[i].for_read || fds[i].for_write)
{
poll_fds[poll_nfds].fd = fds[i].fd;
poll_fds[poll_nfds].events = 0;
poll_fds[poll_nfds].revents = 0;
if (fds[i].for_read)
{
poll_fds[poll_nfds].events |= POLLIN;
TRACE_ADD1 (dbg_help, "r=%d ", fds[i].fd);
}
if (fds[i].for_write)
{
poll_fds[poll_nfds].events |= POLLOUT;
TRACE_ADD1 (dbg_help, "w=%d ", fds[i].fd);
}
poll_nfds++;
any = 1;
}
fds[i].signaled = 0;
}
TRACE_END (dbg_help, "]");
if (!any)
{
free (poll_fds);
return TRACE_SYSRES (0);
}
do
count = poll (poll_fds, poll_nfds, timeout);
while (count < 0 && (errno == EINTR || errno == EAGAIN));
if (count < 0)
{
int save_errno = errno;
free (poll_fds);
errno = save_errno;
return TRACE_SYSRES (-1);
}
TRACE_SEQ (dbg_help, "poll OK [ ");
if (TRACE_ENABLED (dbg_help))
{
poll_nfds = 0;
for (i = 0; i < nfds; i++)
{
if (fds[i].fd == -1)
continue;
if ((poll_fds[poll_nfds].revents & (POLLIN|POLLHUP)))
TRACE_ADD1 (dbg_help, "r=%d ", i);
if ((poll_fds[poll_nfds].revents & POLLOUT))
TRACE_ADD1 (dbg_help, "w=%d ", i);
poll_nfds++;
}
TRACE_END (dbg_help, "]");
}
poll_nfds = 0;
for (i = 0; i < nfds; i++)
{
if (fds[i].fd == -1)
continue;
if (fds[i].for_read || fds[i].for_write)
{
short events_to_be_checked = 0;
if (fds[i].for_read)
events_to_be_checked |= (POLLIN|POLLHUP);
if (fds[i].for_write)
events_to_be_checked |= POLLOUT;
if ((poll_fds[poll_nfds].revents & events_to_be_checked))
fds[i].signaled = 1;
poll_nfds++;
}
}
free (poll_fds);
return TRACE_SYSRES (count);
}
#else
static int
_gpgme_io_select_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
{ {
fd_set readfds; fd_set readfds;
fd_set writefds; fd_set writefds;
@ -802,7 +913,17 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
} }
return TRACE_SYSRES (count); return TRACE_SYSRES (count);
} }
#endif
int
_gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
{
#ifdef HAVE_POLL_H
return _gpgme_io_select_poll (fds, nfds, nonblock);
#else
return _gpgme_io_select_select (fds, nfds, nonblock);
#endif
}
int int
_gpgme_io_recvmsg (int fd, struct msghdr *msg, int flags) _gpgme_io_recvmsg (int fd, struct msghdr *msg, int flags)

View File

@ -38,8 +38,16 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <pthread.h> #include <pthread.h>
#ifdef HAVE_SYS_SELECT_H #ifdef HAVE_POLL_H
# include <poll.h>
#else
# ifdef HAVE_SYS_SELECT_H
# include <sys/select.h> # include <sys/select.h>
# else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# endif
# endif
#endif #endif
#include <gpgme.h> #include <gpgme.h>
@ -116,6 +124,60 @@ io_event (void *data, gpgme_event_io_t type, void *type_data)
} }
#ifdef HAVE_POLL_H
static int
do_select (void)
{
struct pollfd poll_fds[FDLIST_MAX];
nfds_t poll_nfds;
int i, n;
int any = 0;
pthread_mutex_lock (&lock);
poll_nfds = 0;
for (i = 0; i < FDLIST_MAX; i++)
if (fdlist[i].fd != -1)
{
poll_fds[poll_nfds].fd = fdlist[i].fd;
poll_fds[poll_nfds].events = 0;
poll_fds[poll_nfds].revents = 0;
if (fdlist[i].dir)
poll_fds[poll_nfds].events |= POLLIN;
else
poll_fds[poll_nfds].events |= POLLOUT;
poll_nfds++;
}
pthread_mutex_unlock (&lock);
do
{
n = poll (poll_fds, poll_nfds, 1000);
}
while (n < 0 && (errno == EINTR || errno == EAGAIN));
if (n < 0)
return n; /* Error or timeout. */
pthread_mutex_lock (&lock);
poll_nfds = 0;
for (i = 0; i < FDLIST_MAX && n; i++)
{
if (fdlist[i].fd != -1)
{
if ((poll_fds[poll_nfds++].revents
& (fdlist[i].dir ? (POLLIN|POLLHUP) : POLLOUT)))
{
assert (n);
n--;
any = 1;
(*fdlist[i].fnc) (fdlist[i].fnc_data, fdlist[i].fd);
}
}
}
pthread_mutex_unlock (&lock);
return any;
}
#else
static int static int
do_select (void) do_select (void)
{ {
@ -162,6 +224,7 @@ do_select (void)
pthread_mutex_unlock (&lock); pthread_mutex_unlock (&lock);
return any; return any;
} }
#endif
static int static int
my_wait (void) my_wait (void)

View File

@ -31,7 +31,17 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/select.h> #ifdef HAVE_POLL_H
# include <poll.h>
#else
# ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
# else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# endif
# endif
#endif
#include <gpgme.h> #include <gpgme.h>
@ -104,6 +114,56 @@ io_event (void *data, gpgme_event_io_t type, void *type_data)
} }
#ifdef HAVE_POLL_H
int
do_select (void)
{
struct pollfd poll_fds[FDLIST_MAX];
nfds_t poll_nfds;
int i, n;
int any = 0;
poll_nfds = 0;
for (i = 0; i < FDLIST_MAX; i++)
if (fdlist[i].fd != -1)
{
poll_fds[poll_nfds].fd = fdlist[i].fd;
poll_fds[poll_nfds].events = 0;
poll_fds[poll_nfds].revents = 0;
if (fdlist[i].dir)
poll_fds[poll_nfds].events |= POLLIN;
else
poll_fds[poll_nfds].events |= POLLOUT;
poll_nfds++;
}
do
{
n = poll (poll_fds, poll_nfds, 1000);
}
while (n < 0 && (errno == EINTR || errno == EAGAIN));
if (n < 0)
return n; /* Error or timeout. */
poll_nfds = 0;
for (i = 0; i < FDLIST_MAX && n; i++)
{
if (fdlist[i].fd != -1)
{
if ((poll_fds[poll_nfds++].revents
& (fdlist[i].dir ? (POLLIN|POLLHUP) : POLLOUT)))
{
assert (n);
n--;
any = 1;
(*fdlist[i].fnc) (fdlist[i].fnc_data, fdlist[i].fd);
}
}
}
return any;
}
#else
int int
do_select (void) do_select (void)
{ {
@ -146,6 +206,7 @@ do_select (void)
} }
return any; return any;
} }
#endif
int int
my_wait (void) my_wait (void)