summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2023-05-04 01:38:53 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2023-05-28 07:52:32 +0200
commit713342d9b09d717e9942ed08bd620c9159a98fb8 (patch)
tree7478b923d18e578f75d99cecba6ad6efbc343110
parentjournalctl: split out show() (diff)
downloadsystemd-713342d9b09d717e9942ed08bd620c9159a98fb8.tar.xz
systemd-713342d9b09d717e9942ed08bd620c9159a98fb8.zip
journalctl: replace ppoll() loop with sd_event_loop()
No functional change, just refactoring.
-rw-r--r--src/journal/journalctl.c122
1 files changed, 71 insertions, 51 deletions
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 0f1a738fa5..9bfeb121ee 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -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 = show(&c);
- if (r < 0)
- return r;
+ r = setup_event(&c, poll_fd, &e);
+ if (r < 0)
+ return r;
- fflush(stdout);
- }
+ return sd_event_loop(e);
}
r = show(&c);