journalctl: replace ppoll() loop with sd_event_loop()

No functional change, just refactoring.
This commit is contained in:
Yu Watanabe
2023-05-28 14:52:32 +09:00
parent e4c4a9db87
commit 713342d9b0
+71 -51
View File
@@ -2121,41 +2121,6 @@ static int update_cursor(sd_journal *j) {
return 0;
}
static int wait_for_change(sd_journal *j, int poll_fd) {
struct pollfd pollfds[] = {
{ .fd = poll_fd, .events = POLLIN },
{ .fd = STDOUT_FILENO },
};
usec_t timeout;
int r;
assert(j);
assert(poll_fd >= 0);
/* Much like sd_journal_wait() but also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that,
* i.e. when it is closed. */
r = sd_journal_get_timeout(j, &timeout);
if (r < 0)
return log_error_errno(r, "Failed to determine journal waiting time: %m");
r = ppoll_usec(pollfds, ELEMENTSOF(pollfds), timeout);
if (r == -EINTR)
return 0;
if (r < 0)
return log_error_errno(r, "Couldn't wait for journal event: %m");
if (pollfds[1].revents & (POLLHUP|POLLERR)) /* STDOUT has been closed? */
return log_debug_errno(SYNTHETIC_ERRNO(ECANCELED),
"Standard output has been closed.");
r = sd_journal_process(j);
if (r < 0)
return log_error_errno(r, "Failed to process journal events: %m");
return 0;
}
typedef struct Context {
sd_journal *journal;
bool need_seek;
@@ -2305,6 +2270,71 @@ static int show(Context *c) {
return n_shown;
}
static int show_and_fflush(Context *c, sd_event_source *s) {
int r;
assert(c);
assert(s);
r = show(c);
if (r < 0)
return sd_event_exit(sd_event_source_get_event(s), r);
fflush(stdout);
return 0;
}
static int on_journal_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
Context *c = ASSERT_PTR(userdata);
int r;
assert(s);
r = sd_journal_process(c->journal);
if (r < 0) {
log_error_errno(r, "Failed to process journal events: %m");
return sd_event_exit(sd_event_source_get_event(s), r);
}
return show_and_fflush(c, s);
}
static int on_first_event(sd_event_source *s, void *userdata) {
return show_and_fflush(userdata, s);
}
static int setup_event(Context *c, int fd, sd_event **ret) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
int r;
assert(arg_follow);
assert(c);
assert(fd >= 0);
assert(ret);
r = sd_event_default(&e);
if (r < 0)
return log_error_errno(r, "Failed to allocate sd_event object: %m");
r = sd_event_add_io(e, NULL, fd, EPOLLIN, &on_journal_event, c);
if (r < 0)
return log_error_errno(r, "Failed to add io event source for journal: %m");
/* Also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that, i.e. when it is closed. */
r = sd_event_add_io(e, NULL, STDOUT_FILENO, EPOLLHUP|EPOLLERR, NULL, INT_TO_PTR(-ECANCELED));
if (r < 0)
return log_error_errno(r, "Failed to add io event source for stdout: %m");
if (arg_lines != 0 || arg_since_set) {
r = sd_event_add_defer(e, NULL, on_first_event, c);
if (r < 0)
return log_error_errno(r, "Failed to add defer event source: %m");
}
*ret = TAKE_PTR(e);
return 0;
}
static int run(int argc, char *argv[]) {
bool need_seek = false, since_seeked = false, use_cursor = false, after_cursor = false;
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
@@ -2727,25 +2757,15 @@ static int run(int argc, char *argv[]) {
};
if (arg_follow) {
if (arg_lines != 0 || arg_since_set) {
r = show(&c);
if (r < 0)
return r;
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
fflush(stdout);
}
assert(poll_fd >= 0);
for (;;) {
r = wait_for_change(j, poll_fd);
if (r < 0)
return r;
r = setup_event(&c, poll_fd, &e);
if (r < 0)
return r;
r = show(&c);
if (r < 0)
return r;
fflush(stdout);
}
return sd_event_loop(e);
}
r = show(&c);