]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journalctl: replace ppoll() loop with sd_event_loop()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 3 May 2023 23:38:53 +0000 (08:38 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 28 May 2023 05:52:32 +0000 (14:52 +0900)
No functional change, just refactoring.

src/journal/journalctl.c

index 0f1a738fa549028b862f23efbaab62d05967b0f6..9bfeb121eecb02c0ff84604425e035ccca9c08dd 100644 (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 = 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);