|
|
984f77 |
From 67d3aade15bede6b162e8bfe88db60311efb0d1f Mon Sep 17 00:00:00 2001
|
|
|
984f77 |
From: Lennart Poettering <lennart@poettering.net>
|
|
|
984f77 |
Date: Wed, 24 Oct 2018 21:49:52 +0200
|
|
|
984f77 |
Subject: [PATCH] journalctl: in --follow mode watch stdout for POLLHUP/POLLERR
|
|
|
984f77 |
and exit
|
|
|
984f77 |
|
|
|
984f77 |
Fixes: #9374
|
|
|
984f77 |
(cherry picked from commit 2a1e0f2228bbdfbc18635e959f47df7da50b62fe)
|
|
|
984f77 |
|
|
|
984f77 |
Resolves: #2003236
|
|
|
984f77 |
---
|
|
|
984f77 |
src/journal/journalctl.c | 65 +++++++++++++++++++++++++++++-----------
|
|
|
984f77 |
1 file changed, 48 insertions(+), 17 deletions(-)
|
|
|
984f77 |
|
|
|
984f77 |
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
|
|
|
984f77 |
index 56b1be530d..fa83dce562 100644
|
|
|
984f77 |
--- a/src/journal/journalctl.c
|
|
|
984f77 |
+++ b/src/journal/journalctl.c
|
|
|
984f77 |
@@ -2064,14 +2064,46 @@ static int sync_journal(void) {
|
|
|
984f77 |
return send_signal_and_wait(SIGRTMIN+1, "/run/systemd/journal/synced");
|
|
|
984f77 |
}
|
|
|
984f77 |
|
|
|
984f77 |
-int main(int argc, char *argv[]) {
|
|
|
984f77 |
+static int wait_for_change(sd_journal *j, int poll_fd) {
|
|
|
984f77 |
+ struct pollfd pollfds[] = {
|
|
|
984f77 |
+ { .fd = poll_fd, .events = POLLIN },
|
|
|
984f77 |
+ { .fd = STDOUT_FILENO },
|
|
|
984f77 |
+ };
|
|
|
984f77 |
+
|
|
|
984f77 |
+ struct timespec ts;
|
|
|
984f77 |
+ usec_t timeout;
|
|
|
984f77 |
int r;
|
|
|
984f77 |
+
|
|
|
984f77 |
+ assert(j);
|
|
|
984f77 |
+ assert(poll_fd >= 0);
|
|
|
984f77 |
+
|
|
|
984f77 |
+ /* Much like sd_journal_wait() but also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that,
|
|
|
984f77 |
+ * i.e. when it is closed. */
|
|
|
984f77 |
+
|
|
|
984f77 |
+ r = sd_journal_get_timeout(j, &timeout);
|
|
|
984f77 |
+ if (r < 0)
|
|
|
984f77 |
+ return log_error_errno(r, "Failed to determine journal waiting time: %m");
|
|
|
984f77 |
+
|
|
|
984f77 |
+ if (ppoll(pollfds, ELEMENTSOF(pollfds), timeout == USEC_INFINITY ? NULL : timespec_store(&ts, timeout), NULL) < 0)
|
|
|
984f77 |
+ return log_error_errno(errno, "Couldn't wait for journal event: %m");
|
|
|
984f77 |
+
|
|
|
984f77 |
+ if (pollfds[1].revents & (POLLHUP|POLLERR)) { /* STDOUT has been closed? */
|
|
|
984f77 |
+ log_debug("Standard output has been closed.");
|
|
|
984f77 |
+ return -ECANCELED;
|
|
|
984f77 |
+ }
|
|
|
984f77 |
+
|
|
|
984f77 |
+ r = sd_journal_process(j);
|
|
|
984f77 |
+ if (r < 0)
|
|
|
984f77 |
+ return log_error_errno(r, "Failed to process journal events: %m");
|
|
|
984f77 |
+
|
|
|
984f77 |
+ return 0;
|
|
|
984f77 |
+}
|
|
|
984f77 |
+
|
|
|
984f77 |
+int main(int argc, char *argv[]) {
|
|
|
984f77 |
+ bool previous_boot_id_valid = false, first_line = true, ellipsized = false, need_seek = false;
|
|
|
984f77 |
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
|
|
|
984f77 |
- bool need_seek = false;
|
|
|
984f77 |
sd_id128_t previous_boot_id;
|
|
|
984f77 |
- bool previous_boot_id_valid = false, first_line = true;
|
|
|
984f77 |
- int n_shown = 0;
|
|
|
984f77 |
- bool ellipsized = false;
|
|
|
984f77 |
+ int n_shown = 0, r, poll_fd = -1;
|
|
|
984f77 |
|
|
|
984f77 |
setlocale(LC_ALL, "");
|
|
|
984f77 |
log_parse_environment();
|
|
|
984f77 |
@@ -2391,15 +2423,15 @@ int main(int argc, char *argv[]) {
|
|
|
984f77 |
|
|
|
984f77 |
/* Opening the fd now means the first sd_journal_wait() will actually wait */
|
|
|
984f77 |
if (arg_follow) {
|
|
|
984f77 |
- r = sd_journal_get_fd(j);
|
|
|
984f77 |
- if (r == -EMFILE) {
|
|
|
984f77 |
- log_warning("Insufficent watch descriptors available. Reverting to -n.");
|
|
|
984f77 |
+ poll_fd = sd_journal_get_fd(j);
|
|
|
984f77 |
+ if (poll_fd == -EMFILE) {
|
|
|
984f77 |
+ log_warning_errno(poll_fd, "Insufficent watch descriptors available. Reverting to -n.");
|
|
|
984f77 |
arg_follow = false;
|
|
|
984f77 |
- } else if (r == -EMEDIUMTYPE) {
|
|
|
984f77 |
- log_error_errno(r, "The --follow switch is not supported in conjunction with reading from STDIN.");
|
|
|
984f77 |
+ } else if (poll_fd == -EMEDIUMTYPE) {
|
|
|
984f77 |
+ log_error_errno(poll_fd, "The --follow switch is not supported in conjunction with reading from STDIN.");
|
|
|
984f77 |
goto finish;
|
|
|
984f77 |
- } else if (r < 0) {
|
|
|
984f77 |
- log_error_errno(r, "Failed to get journal fd: %m");
|
|
|
984f77 |
+ } else if (poll_fd < 0) {
|
|
|
984f77 |
+ log_error_errno(poll_fd, "Failed to get journal fd: %m");
|
|
|
984f77 |
goto finish;
|
|
|
984f77 |
}
|
|
|
984f77 |
}
|
|
|
984f77 |
@@ -2621,7 +2653,7 @@ int main(int argc, char *argv[]) {
|
|
|
984f77 |
need_seek = true;
|
|
|
984f77 |
if (r == -EADDRNOTAVAIL)
|
|
|
984f77 |
break;
|
|
|
984f77 |
- else if (r < 0 || ferror(stdout))
|
|
|
984f77 |
+ else if (r < 0)
|
|
|
984f77 |
goto finish;
|
|
|
984f77 |
|
|
|
984f77 |
n_shown++;
|
|
|
984f77 |
@@ -2659,11 +2691,10 @@ int main(int argc, char *argv[]) {
|
|
|
984f77 |
}
|
|
|
984f77 |
|
|
|
984f77 |
fflush(stdout);
|
|
|
984f77 |
- r = sd_journal_wait(j, (uint64_t) -1);
|
|
|
984f77 |
- if (r < 0) {
|
|
|
984f77 |
- log_error_errno(r, "Couldn't wait for journal event: %m");
|
|
|
984f77 |
+
|
|
|
984f77 |
+ r = wait_for_change(j, poll_fd);
|
|
|
984f77 |
+ if (r < 0)
|
|
|
984f77 |
goto finish;
|
|
|
984f77 |
- }
|
|
|
984f77 |
|
|
|
984f77 |
first_line = false;
|
|
|
984f77 |
}
|