tree-wide: port to fd_wait_for_event()

Prompted by the discussion on #16110, let's migrate more code to
fd_wait_for_event().

This only leaves 7 places where we call into poll()/poll() directly in
our entire codebase. (one of which is fd_wait_for_event() itself)
This commit is contained in:
Lennart Poettering 2020-06-10 11:43:40 +02:00 committed by Daan De Meyer
parent 24bd74ae03
commit 0f2d351f79
11 changed files with 63 additions and 163 deletions

View file

@ -11,10 +11,6 @@
#include "time-util.h"
int flush_fd(int fd) {
struct pollfd pollfd = {
.fd = fd,
.events = POLLIN,
};
int count = 0;
/* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
@ -27,22 +23,18 @@ int flush_fd(int fd) {
ssize_t l;
int r;
r = poll(&pollfd, 1, 0);
r = fd_wait_for_event(fd, POLLIN, 0);
if (r < 0) {
if (errno == EINTR)
if (r == -EINTR)
continue;
return -errno;
return r;
}
if (r == 0)
return count;
if (pollfd.revents & POLLNVAL)
return -EBADF;
l = read(fd, buf, sizeof(buf));
if (l < 0) {
if (errno == EINTR)
continue;
@ -158,24 +150,15 @@ int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
}
int pipe_eof(int fd) {
struct pollfd pollfd = {
.fd = fd,
.events = POLLIN|POLLHUP,
};
int r;
r = poll(&pollfd, 1, 0);
r = fd_wait_for_event(fd, POLLIN, 0);
if (r < 0)
return -errno;
return r;
if (r == 0)
return 0;
if (pollfd.revents & POLLNVAL)
return -EBADF;
return pollfd.revents & POLLHUP;
return !!(r & POLLHUP);
}
int fd_wait_for_event(int fd, int event, usec_t t) {

View file

@ -21,6 +21,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
#include "io-util.h"
#include "log.h"
#include "macro.h"
#include "memory-util.h"
@ -968,10 +969,6 @@ fallback:
int flush_accept(int fd) {
struct pollfd pollfd = {
.fd = fd,
.events = POLLIN,
};
int r, b;
socklen_t l = sizeof(b);
@ -992,19 +989,16 @@ int flush_accept(int fd) {
for (unsigned iteration = 0;; iteration++) {
int cfd;
r = poll(&pollfd, 1, 0);
r = fd_wait_for_event(fd, POLLIN, 0);
if (r < 0) {
if (errno == EINTR)
if (r == -EINTR)
continue;
return -errno;
return r;
}
if (r == 0)
return 0;
if (pollfd.revents & POLLNVAL)
return -EBADF;
if (iteration >= MAX_FLUSH_ITERATIONS)
return log_debug_errno(SYNTHETIC_ERRNO(EBUSY),
"Failed to flush connections within " STRINGIFY(MAX_FLUSH_ITERATIONS) " iterations.");

View file

@ -1262,23 +1262,15 @@ int bus_socket_read_message(sd_bus *bus) {
}
int bus_socket_process_opening(sd_bus *b) {
int error = 0;
int error = 0, events, r;
socklen_t slen = sizeof(error);
struct pollfd p = {
.fd = b->output_fd,
.events = POLLOUT,
};
int r;
assert(b->state == BUS_OPENING);
r = poll(&p, 1, 0);
if (r < 0)
return -errno;
if (p.revents & POLLNVAL)
return -EBADF;
if (!(p.revents & (POLLOUT|POLLERR|POLLHUP)))
events = fd_wait_for_event(b->output_fd, POLLOUT, 0);
if (events < 0)
return events;
if (!(events & (POLLOUT|POLLERR|POLLHUP)))
return 0;
r = getsockopt(b->output_fd, SOL_SOCKET, SO_ERROR, &error, &slen);
@ -1286,7 +1278,7 @@ int bus_socket_process_opening(sd_bus *b) {
b->last_connect_error = errno;
else if (error != 0)
b->last_connect_error = error;
else if (p.revents & (POLLERR|POLLHUP))
else if (events & (POLLERR|POLLHUP))
b->last_connect_error = ECONNREFUSED;
else
return bus_socket_start_auth(b);

View file

@ -555,7 +555,6 @@ finish:
_public_ int sd_notify_barrier(int unset_environment, uint64_t timeout) {
_cleanup_close_pair_ int pipe_fd[2] = { -1, -1 };
struct timespec ts;
int r;
if (pipe2(pipe_fd, O_CLOEXEC) < 0)
@ -567,18 +566,11 @@ _public_ int sd_notify_barrier(int unset_environment, uint64_t timeout) {
pipe_fd[1] = safe_close(pipe_fd[1]);
struct pollfd pfd = {
.fd = pipe_fd[0],
/* POLLHUP is implicit */
.events = 0,
};
r = ppoll(&pfd, 1, timeout == UINT64_MAX ? NULL : timespec_store(&ts, timeout), NULL);
r = fd_wait_for_event(pipe_fd[0], 0 /* POLLHUP is implicit */, timeout);
if (r < 0)
return -errno;
return r;
if (r == 0)
return -ETIMEDOUT;
if (pfd.revents & POLLNVAL)
return -EBADF;
return 1;
}

View file

@ -7,6 +7,7 @@
#include "alloc-util.h"
#include "fd-util.h"
#include "hashmap.h"
#include "io-util.h"
#include "macro.h"
#include "netlink-internal.h"
#include "netlink-slot.h"
@ -462,7 +463,6 @@ static usec_t calc_elapse(uint64_t usec) {
}
static int rtnl_poll(sd_netlink *rtnl, bool need_more, uint64_t timeout_usec) {
struct timespec ts;
usec_t m = USEC_INFINITY;
int r, e;
@ -491,23 +491,15 @@ static int rtnl_poll(sd_netlink *rtnl, bool need_more, uint64_t timeout_usec) {
}
}
if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
if (timeout_usec != (uint64_t) -1 && (m == USEC_INFINITY || timeout_usec < m))
m = timeout_usec;
struct pollfd p = {
.fd = rtnl->fd,
.events = e,
};
r = ppoll(&p, 1, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
r = fd_wait_for_event(rtnl->fd, e, m);
if (r < 0)
return -errno;
return r;
if (r == 0)
return 0;
if (p.revents & POLLNVAL)
return -EBADF;
return 1;
}

View file

@ -9,6 +9,7 @@
#include "device-monitor-private.h"
#include "device-private.h"
#include "device-util.h"
#include "io-util.h"
#include "libudev-device-internal.h"
#include "string-util.h"
@ -191,17 +192,11 @@ _public_ int udev_monitor_get_fd(struct udev_monitor *udev_monitor) {
}
static int udev_monitor_receive_sd_device(struct udev_monitor *udev_monitor, sd_device **ret) {
struct pollfd pfd;
int r;
assert(udev_monitor);
assert(ret);
pfd = (struct pollfd) {
.fd = device_monitor_get_fd(udev_monitor->monitor),
.events = POLLIN,
};
for (;;) {
/* r == 0 means a device is received but it does not pass the current filter. */
r = device_monitor_receive_device(udev_monitor->monitor, ret);
@ -209,20 +204,18 @@ static int udev_monitor_receive_sd_device(struct udev_monitor *udev_monitor, sd_
return r;
for (;;) {
/* wait next message */
r = poll(&pfd, 1, 0);
/* Wait for next message */
r = fd_wait_for_event(device_monitor_get_fd(udev_monitor->monitor), POLLIN, 0);
if (r < 0) {
if (IN_SET(errno, EINTR, EAGAIN))
if (IN_SET(r, -EINTR, -EAGAIN))
continue;
return -errno;
return r;
}
if (r == 0)
return -EAGAIN;
if (pfd.revents & POLLNVAL)
return -EBADF;
/* receive next message */
/* Receive next message */
break;
}
}

View file

@ -14,6 +14,7 @@
#include "alloc-util.h"
#include "fd-util.h"
#include "hostname-util.h"
#include "io-util.h"
#include "macro.h"
#include "memory-util.h"
#include "path-util.h"
@ -297,7 +298,7 @@ int utmp_put_runlevel(int runlevel, int previous) {
return write_entry_both(&store);
}
#define TIMEOUT_MSEC 50
#define TIMEOUT_USEC (50 * USEC_PER_MSEC)
static int write_to_terminal(const char *tty, const char *message) {
_cleanup_close_ int fd = -1;
@ -315,14 +316,10 @@ static int write_to_terminal(const char *tty, const char *message) {
p = message;
left = strlen(message);
end = now(CLOCK_MONOTONIC) + TIMEOUT_MSEC*USEC_PER_MSEC;
end = now(CLOCK_MONOTONIC) + TIMEOUT_USEC;
while (left > 0) {
ssize_t n;
struct pollfd pollfd = {
.fd = fd,
.events = POLLOUT,
};
usec_t t;
int k;
@ -331,13 +328,11 @@ static int write_to_terminal(const char *tty, const char *message) {
if (t >= end)
return -ETIME;
k = poll(&pollfd, 1, (end - t) / USEC_PER_MSEC);
k = fd_wait_for_event(fd, POLLOUT, end - t);
if (k < 0)
return -errno;
return k;
if (k == 0)
return -ETIME;
if (pollfd.revents & POLLNVAL)
return -EBADF;
n = write(fd, p, left);
if (n < 0) {

View file

@ -6,6 +6,7 @@
#include "errno-util.h"
#include "fd-util.h"
#include "hashmap.h"
#include "io-util.h"
#include "list.h"
#include "process-util.h"
#include "set.h"
@ -1003,8 +1004,6 @@ static void handle_revents(Varlink *v, int revents) {
}
int varlink_wait(Varlink *v, usec_t timeout) {
struct timespec ts;
struct pollfd pfd;
int r, fd, events;
usec_t t;
@ -1038,23 +1037,13 @@ int varlink_wait(Varlink *v, usec_t timeout) {
if (events < 0)
return events;
pfd = (struct pollfd) {
.fd = fd,
.events = events,
};
r = ppoll(&pfd, 1,
t == USEC_INFINITY ? NULL : timespec_store(&ts, t),
NULL);
r = fd_wait_for_event(fd, events, t);
if (r < 0)
return -errno;
return r;
if (r == 0)
return 0;
if (pfd.revents & POLLNVAL)
return -EBADF;
handle_revents(v, pfd.revents);
handle_revents(v, r);
return 1;
}
@ -1123,8 +1112,6 @@ int varlink_flush(Varlink *v) {
return -ENOTCONN;
for (;;) {
struct pollfd pfd;
if (v->output_buffer_size == 0)
break;
if (v->write_disconnected)
@ -1138,20 +1125,13 @@ int varlink_flush(Varlink *v) {
continue;
}
pfd = (struct pollfd) {
.fd = v->fd,
.events = POLLOUT,
};
r = poll(&pfd, 1, -1);
r = fd_wait_for_event(v->fd, POLLOUT, USEC_INFINITY);
if (r < 0)
return -errno;
return r;
assert(r > 0);
if (pfd.revents & POLLNVAL)
return -EBADF;
assert(r != 0);
handle_revents(v, pfd.revents);
handle_revents(v, r);
}
return ret;

View file

@ -23,6 +23,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
#include "io-util.h"
#include "log.h"
#include "main-func.h"
#include "parse-util.h"
@ -239,7 +240,6 @@ static int execute_s2h(const SleepConfig *sleep_config) {
_cleanup_close_ int tfd = -1;
char buf[FORMAT_TIMESPAN_MAX];
struct itimerspec ts = {};
struct pollfd fds;
int r;
assert(sleep_config);
@ -261,34 +261,25 @@ static int execute_s2h(const SleepConfig *sleep_config) {
if (r < 0)
return r;
fds = (struct pollfd) {
.fd = tfd,
.events = POLLIN,
};
r = poll(&fds, 1, 0);
r = fd_wait_for_event(tfd, POLLIN, 0);
if (r < 0)
return log_error_errno(errno, "Error polling timerfd: %m");
return log_error_errno(r, "Error polling timerfd: %m");
if (!FLAGS_SET(r, POLLIN)) /* We woke up before the alarm time, we are done. */
return 0;
tfd = safe_close(tfd);
if (FLAGS_SET(fds.revents, POLLNVAL))
return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Invalid timer fd to sleep on?");
if (!FLAGS_SET(fds.revents, POLLIN)) /* We woke up before the alarm time, we are done. */
return 0;
/* If woken up after alarm time, hibernate */
log_debug("Attempting to hibernate after waking from %s timer",
format_timespan(buf, sizeof(buf), sleep_config->hibernate_delay_sec, USEC_PER_SEC));
r = execute(sleep_config->hibernate_modes, sleep_config->hibernate_states);
if (r < 0) {
log_notice("Couldn't hibernate, will try to suspend again.");
log_notice_errno(r, "Couldn't hibernate, will try to suspend again.");
r = execute(sleep_config->suspend_modes, sleep_config->suspend_states);
if (r < 0) {
log_notice("Could neither hibernate nor suspend again, giving up.");
return r;
}
if (r < 0)
return log_notice_errno(r, "Could neither hibernate nor suspend again, giving up.");
}
return 0;

View file

@ -15,6 +15,7 @@
#include "sd-bus.h"
#include "sd-login.h"
#include "io-util.h"
#include "libudev-util.h"
#include "string-util.h"
#include "strv.h"
@ -141,9 +142,8 @@ static int emit_deprecation_warning(void) {
int settle_main(int argc, char *argv[], void *userdata) {
_cleanup_(udev_queue_unrefp) struct udev_queue *queue = NULL;
struct pollfd pfd;
usec_t deadline;
int r;
int r, fd;
r = parse_argv(argc, argv);
if (r <= 0)
@ -177,17 +177,12 @@ int settle_main(int argc, char *argv[], void *userdata) {
if (!queue)
return log_error_errno(errno, "Failed to get udev queue: %m");
r = udev_queue_get_fd(queue);
if (r < 0) {
log_debug_errno(r, "Queue is empty, nothing to watch.");
fd = udev_queue_get_fd(queue);
if (fd < 0) {
log_debug_errno(fd, "Queue is empty, nothing to watch: %m");
return 0;
}
pfd = (struct pollfd) {
.events = POLLIN,
.fd = r,
};
(void) emit_deprecation_warning();
for (;;) {
@ -202,12 +197,10 @@ int settle_main(int argc, char *argv[], void *userdata) {
return -ETIMEDOUT;
/* wake up when queue becomes empty */
r = poll(&pfd, 1, MSEC_PER_SEC);
r = fd_wait_for_event(fd, POLLIN, MSEC_PER_SEC);
if (r < 0)
return -errno;
if (pfd.revents & POLLNVAL)
return -EBADF;
if (r > 0 && pfd.revents & POLLIN) {
return r;
if (r & POLLIN) {
r = udev_queue_flush(queue);
if (r < 0)
return log_error_errno(r, "Failed to flush queue: %m");

View file

@ -9,6 +9,7 @@
#include "fd-util.h"
#include "group-record-nss.h"
#include "group-record.h"
#include "io-util.h"
#include "main-func.h"
#include "process-util.h"
#include "strv.h"
@ -747,20 +748,14 @@ static int run(int argc, char *argv[]) {
return log_error_errno(fd, "Failed to accept() from listening socket: %m");
if (now(CLOCK_MONOTONIC) <= usec_add(n, PRESSURE_SLEEP_TIME_USEC)) {
struct pollfd pfd = {
.fd = listen_fd,
.events = POLLIN,
};
/* We only slept a very short time? If so, let's see if there are more sockets
* pending, and if so, let's ask our parent for more workers */
if (poll(&pfd, 1, 0) < 0)
return log_error_errno(errno, "Failed to test for POLLIN on listening socket: %m");
if (FLAGS_SET(pfd.revents, POLLNVAL))
return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Listening socket dead?");
r = fd_wait_for_event(listen_fd, POLLIN, 0);
if (r < 0)
return log_error_errno(r, "Failed to test for POLLIN on listening socket: %m");
if (FLAGS_SET(pfd.revents, POLLIN)) {
if (FLAGS_SET(r, POLLIN)) {
pid_t parent;
parent = getppid();