diff options
author | NIIBE Yutaka <[email protected]> | 2021-11-25 02:13:17 +0000 |
---|---|---|
committer | NIIBE Yutaka <[email protected]> | 2021-11-25 02:13:17 +0000 |
commit | 8148237cb4ae20755c06a44d71761c7030973c3d (patch) | |
tree | aaa3d581d5094f436a6ec353f390b25f902d206d /src/posix-io.c | |
parent | gpgme.pc: Fix library dependency and use of includedir, libdir. (diff) | |
download | gpgme-8148237cb4ae20755c06a44d71761c7030973c3d.tar.gz gpgme-8148237cb4ae20755c06a44d71761c7030973c3d.zip |
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 <[email protected]>
Diffstat (limited to 'src/posix-io.c')
-rw-r--r-- | src/posix-io.c | 125 |
1 files changed, 123 insertions, 2 deletions
diff --git a/src/posix-io.c b/src/posix-io.c index 2a3a81fc..5c6cf1df 100644 --- a/src/posix-io.c +++ b/src/posix-io.c @@ -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 nothing to select, > 0 = number of signaled fds. */ -int -_gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock) +#ifdef HAVE_POLL_H +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 writefds; @@ -802,7 +913,17 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock) } 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 _gpgme_io_recvmsg (int fd, struct msghdr *msg, int flags) |