aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2021-11-25 02:13:17 +0000
committerNIIBE Yutaka <[email protected]>2021-11-25 02:13:17 +0000
commit8148237cb4ae20755c06a44d71761c7030973c3d (patch)
treeaaa3d581d5094f436a6ec353f390b25f902d206d
parentgpgme.pc: Fix library dependency and use of includedir, libdir. (diff)
downloadgpgme-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]>
-rw-r--r--configure.ac2
-rw-r--r--src/ath.c15
-rw-r--r--src/ath.h13
-rw-r--r--src/posix-io.c125
-rw-r--r--tests/gpg/t-cancel.c67
-rw-r--r--tests/gpg/t-eventloop.c63
6 files changed, 269 insertions, 16 deletions
diff --git a/configure.ac b/configure.ac
index 296553e3..4ce30677 100644
--- a/configure.ac
+++ b/configure.ac
@@ -538,7 +538,7 @@ AM_CONDITIONAL(RUN_G13_TESTS, test "$run_g13_test" = "yes")
# Checks for header files.
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.
diff --git a/src/ath.c b/src/ath.c
index 6cc84aa5..996143dc 100644
--- a/src/ath.c
+++ b/src/ath.c
@@ -26,11 +26,15 @@
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
-#ifdef HAVE_SYS_SELECT_H
-# include <sys/select.h>
+#ifdef HAVE_POLL_H
+# include <poll.h>
#else
-# ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
+# ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+# else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# endif
# endif
#endif
#ifdef HAVE_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
ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
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);
#endif
}
-
+#endif
gpgme_ssize_t
ath_waitpid (pid_t pid, int *status, int options)
diff --git a/src/ath.h b/src/ath.h
index d4c1c6fa..8243864a 100644
--- a/src/ath.h
+++ b/src/ath.h
@@ -32,12 +32,15 @@
# include <io.h>
#else /*!HAVE_W32_SYSTEM*/
-
-# ifdef HAVE_SYS_SELECT_H
-# include <sys/select.h>
+# ifdef HAVE_POLL_H
+# include <poll.h>
# else
-# ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
+# ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+# else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# endif
# endif
# endif
# ifdef HAVE_SYS_TYPES_H
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)
diff --git a/tests/gpg/t-cancel.c b/tests/gpg/t-cancel.c
index 48158fbd..d5fb6664 100644
--- a/tests/gpg/t-cancel.c
+++ b/tests/gpg/t-cancel.c
@@ -38,8 +38,16 @@
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
-#ifdef HAVE_SYS_SELECT_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>
@@ -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
do_select (void)
{
@@ -162,6 +224,7 @@ do_select (void)
pthread_mutex_unlock (&lock);
return any;
}
+#endif
static int
my_wait (void)
diff --git a/tests/gpg/t-eventloop.c b/tests/gpg/t-eventloop.c
index b31764ea..0106670b 100644
--- a/tests/gpg/t-eventloop.c
+++ b/tests/gpg/t-eventloop.c
@@ -31,7 +31,17 @@
#include <assert.h>
#include <errno.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>
@@ -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
do_select (void)
{
@@ -146,6 +206,7 @@ do_select (void)
}
return any;
}
+#endif
int
my_wait (void)