From 5f04eea3b1c9a41417ed63e5348b2aabca5542fa Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Wed, 29 Sep 2021 22:29:51 +0200 Subject: [PATCH] interactive: Avoid select(2) in input_available(). In analogy to write_ok(), introduce read_ok() which uses poll(2) rather than select(2). To avoid duplications, abstract out the common code to the new xpoll() helper. We could avoid the timeout parameter of xpoll() at this point because both callers call it with a zero timeout (causing poll() to return immediately), but later patches introduce other callers which specify non-zero timeouts. --- fd.c | 39 +++++++++++++++++++++++++++++++-------- fd.h | 1 + interactive.c | 15 ++------------- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/fd.c b/fd.c index 2f3ec997..63c0337b 100644 --- a/fd.c +++ b/fd.c @@ -644,6 +644,33 @@ int para_munmap(void *start, size_t length) return -ERRNO_TO_PARA_ERROR(err); } +static int xpoll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + int ret; + + do + ret = poll(fds, nfds, timeout); + while (ret < 0 && errno == EINTR); + return ret < 0? -ERRNO_TO_PARA_ERROR(errno) : ret; +} + +/** + * Check a file descriptor for readability. + * + * \param fd The file descriptor. + * + * \return positive if fd is ready for reading, zero if it isn't, negative if + * an error occurred. + * + * \sa \ref write_ok(). + */ +int read_ok(int fd) +{ + struct pollfd pfd = {.fd = fd, .events = POLLIN}; + int ret = xpoll(&pfd, 1, 0); + return ret < 0? ret : pfd.revents & POLLIN; +} + /** * Check a file descriptor for writability. * @@ -651,18 +678,14 @@ int para_munmap(void *start, size_t length) * * \return positive if fd is ready for writing, zero if it isn't, negative if * an error occurred. + * + * \sa \ref read_ok(). */ int write_ok(int fd) { - int ret; struct pollfd pfd = {.fd = fd, .events = POLLOUT}; - - do - ret = poll(&pfd, 1, 0); - while (ret < 0 && errno == EINTR); - if (ret < 0) - return -ERRNO_TO_PARA_ERROR(errno); - return pfd.revents & POLLOUT; + int ret = xpoll(&pfd, 1, 0); + return ret < 0? ret : pfd.revents & POLLOUT; } /** diff --git a/fd.h b/fd.h index 820e1cc9..31b0c88c 100644 --- a/fd.h +++ b/fd.h @@ -17,6 +17,7 @@ int para_chdir(const char *path); int mmap_full_file(const char *filename, int open_mode, void **map, size_t *size, int *fd_ptr); int para_munmap(void *start, size_t length); +int read_ok(int fd); int write_ok(int fd); void valid_fd_012(void); int readv_nonblock(int fd, struct iovec *iov, int iovcnt, fd_set *rfds, diff --git a/interactive.c b/interactive.c index 8e614840..3af90a68 100644 --- a/interactive.c +++ b/interactive.c @@ -258,17 +258,6 @@ static void clear_bottom_line(void) rl_point = point; } -static bool input_available(void) -{ - fd_set rfds; - int ret; - - FD_ZERO(&rfds); - FD_SET(i9ep->ici->fds[0], &rfds); - ret = para_select(1, &rfds, NULL, 0); - return ret > 0; -} - static void i9e_line_handler(char *line) { int ret; @@ -309,7 +298,7 @@ static int i9e_post_select(__a_unused struct sched *s, __a_unused void *context) ret = 0; if (i9ep->caught_sigint) goto rm_btrn; - while (input_available()) { + while (read_ok(i9ep->ici->fds[0]) > 0) { if (i9ep->stdout_btrn) { while (i9ep->key_sequence_length < sizeof(i9ep->key_sequence) - 1) { buf = i9ep->key_sequence + i9ep->key_sequence_length; @@ -326,7 +315,7 @@ static int i9e_post_select(__a_unused struct sched *s, __a_unused void *context) i9ep->key_sequence_length++; rl_stuff_char((int)(unsigned char)*buf); rl_callback_read_char(); - if (!input_available()) + if (read_ok(i9ep->ici->fds[0]) <= 0) break; } i9ep->key_sequence_length = 0; -- 2.39.2