[systemd-commits] 2 commits - man/journalctl.xml src/core TODO

Zbigniew Jędrzejewski-Szmek zbyszek at kemper.freedesktop.org
Mon Jul 15 18:35:24 PDT 2013


 TODO                   |    2 -
 man/journalctl.xml     |   14 ++++++++
 src/core/execute.c     |   42 ++++++++++++++++++++------
 src/core/manager.c     |   78 +++++++++++++++++++++++++++++++++++++++++++++++--
 src/core/manager.h     |    7 +++-
 src/core/transaction.c |    5 ++-
 src/core/unit.c        |   12 +++++--
 7 files changed, 140 insertions(+), 20 deletions(-)

New commits:
commit 31a7eb86f18b0466681d6fbe80c148f96c551c80
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Mon Jul 15 21:34:57 2013 -0400

    systemd: do not output status messages once gettys are running
    
    Make Type=idle communication bidirectional: when bootup is finished,
    the manager, as before, signals idling Type=idle jobs to continue.
    However, if the boot takes too long, idling jobs signal the manager
    that they have had enough, wait a tiny bit more, and continue, taking
    ownership of the console. The manager, when signalled that Type=idle
    jobs are done, makes a note and will not write to the console anymore.
    
    This is a cosmetic issue, but quite noticable, so let's just fix it.
    
    Based on Harald Hoyer's patch.
    
    https://bugs.freedesktop.org/show_bug.cgi?id=54247
    http://unix.stackexchange.com/questions/51805/systemd-messages-after-starting-login/

diff --git a/src/core/execute.c b/src/core/execute.c
index 50d2d49..43b571e 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -69,6 +69,7 @@
 #include "unit.h"
 
 #define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
+#define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC)
 
 /* This assumes there is a 'tty' group */
 #define TTY_MODE 0620
@@ -977,6 +978,35 @@ static int apply_seccomp(uint32_t *syscall_filter) {
         return 0;
 }
 
+static void do_idle_pipe_dance(int idle_pipe[4]) {
+        assert(idle_pipe);
+
+        if (idle_pipe[1] >= 0)
+                close_nointr_nofail(idle_pipe[1]);
+        if (idle_pipe[2] >= 0)
+                close_nointr_nofail(idle_pipe[2]);
+
+        if (idle_pipe[0] >= 0) {
+                int r;
+
+                r = fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC);
+
+                if (idle_pipe[3] >= 0 && r == 0 /* timeout */) {
+                        /* Signal systemd that we are bored and want to continue. */
+                        write(idle_pipe[3], "x", 1);
+
+                        /* Wait for systemd to react to the signal above. */
+                        fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC);
+                }
+
+                close_nointr_nofail(idle_pipe[0]);
+
+        }
+
+        if (idle_pipe[3] >= 0)
+                close_nointr_nofail(idle_pipe[3]);
+}
+
 int exec_spawn(ExecCommand *command,
                char **argv,
                ExecContext *context,
@@ -989,7 +1019,7 @@ int exec_spawn(ExecCommand *command,
                CGroupControllerMask cgroup_mask,
                const char *cgroup_path,
                const char *unit_id,
-               int idle_pipe[2],
+               int idle_pipe[4],
                pid_t *ret) {
 
         _cleanup_strv_free_ char **files_env = NULL;
@@ -1083,14 +1113,8 @@ int exec_spawn(ExecCommand *command,
                         goto fail_child;
                 }
 
-                if (idle_pipe) {
-                        if (idle_pipe[1] >= 0)
-                                close_nointr_nofail(idle_pipe[1]);
-                        if (idle_pipe[0] >= 0) {
-                                fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC);
-                                close_nointr_nofail(idle_pipe[0]);
-                        }
-                }
+                if (idle_pipe)
+                        do_idle_pipe_dance(idle_pipe);
 
                 /* Close sockets very early to make sure we don't
                  * block init reexecution because it cannot bind its
diff --git a/src/core/manager.c b/src/core/manager.c
index 2e98181..ad1a8d6 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -273,6 +273,58 @@ static void manager_print_jobs_in_progress(Manager *m) {
         m->jobs_in_progress_iteration++;
 }
 
+static int manager_watch_idle_pipe(Manager *m) {
+        struct epoll_event ev = {
+                .events = EPOLLIN,
+                .data.ptr = &m->idle_pipe_watch,
+        };
+        int r;
+
+        if (m->idle_pipe_watch.type != WATCH_INVALID)
+                return 0;
+
+        if (m->idle_pipe[2] < 0)
+                return 0;
+
+        m->idle_pipe_watch.type = WATCH_IDLE_PIPE;
+        m->idle_pipe_watch.fd = m->idle_pipe[2];
+        if (m->idle_pipe_watch.fd < 0) {
+                log_error("Failed to create timerfd: %m");
+                r = -errno;
+                goto err;
+        }
+
+        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_pipe_watch.fd, &ev) < 0) {
+                log_error("Failed to add idle_pipe fd to epoll: %m");
+                r = -errno;
+                goto err;
+        }
+
+        log_debug("Set up idle_pipe watch.");
+        log_debug("m->epoll_fd=%d m->idle_pipe_watch.fd=%d",
+                  m->epoll_fd, m->idle_pipe_watch.fd);
+
+        return 0;
+
+err:
+        if (m->idle_pipe_watch.fd >= 0)
+                close_nointr_nofail(m->idle_pipe_watch.fd);
+        watch_init(&m->idle_pipe_watch);
+        return r;
+}
+
+static void manager_unwatch_idle_pipe(Manager *m) {
+        if (m->idle_pipe_watch.type != WATCH_IDLE_PIPE)
+                return;
+
+        log_debug("m->epoll_fd=%d m->idle_pipe_watch.fd=%d",
+                  m->epoll_fd, m->idle_pipe_watch.fd);
+        assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, m->idle_pipe_watch.fd, NULL) >= 0);
+        watch_init(&m->idle_pipe_watch);
+
+        log_debug("Closed idle_pipe watch.");
+}
+
 static int manager_setup_time_change(Manager *m) {
         struct epoll_event ev = {
                 .events = EPOLLIN,
@@ -445,7 +497,7 @@ int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **_m) {
         m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
         m->exit_code = _MANAGER_EXIT_CODE_INVALID;
         m->pin_cgroupfs_fd = -1;
-        m->idle_pipe[0] = m->idle_pipe[1] = -1;
+        m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] = m->idle_pipe[3] = -1;
 
         watch_init(&m->signal_watch);
         watch_init(&m->mount_watch);
@@ -657,6 +709,11 @@ static void manager_clear_jobs_and_units(Manager *m) {
         m->n_running_jobs = 0;
 }
 
+static void close_idle_pipe(Manager *m) {
+        close_pipe(m->idle_pipe);
+        close_pipe(m->idle_pipe + 2);
+}
+
 void manager_free(Manager *m) {
         UnitType c;
         int i;
@@ -701,7 +758,7 @@ void manager_free(Manager *m) {
         hashmap_free(m->cgroup_unit);
         set_free_free(m->unit_path_cache);
 
-        close_pipe(m->idle_pipe);
+        close_idle_pipe(m);
 
         free(m->switch_root);
         free(m->switch_root_init);
@@ -1138,6 +1195,9 @@ unsigned manager_dispatch_run_queue(Manager *m) {
         if (m->n_running_jobs > 0)
                 manager_watch_jobs_in_progress(m);
 
+        if (m->n_on_console > 0)
+                manager_watch_idle_pipe(m);
+
         return n;
 }
 
@@ -1691,6 +1751,14 @@ static int process_event(Manager *m, struct epoll_event *ev) {
                 break;
         }
 
+        case WATCH_IDLE_PIPE: {
+                m->no_console_output = true;
+
+                manager_unwatch_idle_pipe(m);
+                close_idle_pipe(m);
+                break;
+        }
+
         default:
                 log_error("event type=%i", w->type);
                 assert_not_reached("Unknown epoll event type.");
@@ -2384,7 +2452,8 @@ void manager_check_finished(Manager *m) {
         }
 
         /* Notify Type=idle units that we are done now */
-        close_pipe(m->idle_pipe);
+        manager_unwatch_idle_pipe(m);
+        close_idle_pipe(m);
 
         /* Turn off confirm spawn now */
         m->confirm_spawn = false;
@@ -2660,6 +2729,9 @@ static bool manager_get_show_status(Manager *m) {
         if (m->running_as != SYSTEMD_SYSTEM)
                 return false;
 
+        if (m->no_console_output)
+                return false;
+
         if (m->show_status)
                 return true;
 
diff --git a/src/core/manager.h b/src/core/manager.h
index 6d52414..bd068ac 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -63,7 +63,8 @@ enum WatchType {
         WATCH_DBUS_WATCH,
         WATCH_DBUS_TIMEOUT,
         WATCH_TIME_CHANGE,
-        WATCH_JOBS_IN_PROGRESS
+        WATCH_JOBS_IN_PROGRESS,
+        WATCH_IDLE_PIPE,
 };
 
 struct Watch {
@@ -135,6 +136,7 @@ struct Manager {
         Watch signal_watch;
         Watch time_change_watch;
         Watch jobs_in_progress_watch;
+        Watch idle_pipe_watch;
 
         int epoll_fd;
 
@@ -227,6 +229,7 @@ struct Manager {
 
         bool show_status;
         bool confirm_spawn;
+        bool no_console_output;
 
         ExecOutput default_std_output, default_std_error;
 
@@ -244,7 +247,7 @@ struct Manager {
         unsigned jobs_in_progress_iteration;
 
         /* Type=idle pipes */
-        int idle_pipe[2];
+        int idle_pipe[4];
 
         char *switch_root;
         char *switch_root_init;
diff --git a/src/core/transaction.c b/src/core/transaction.c
index 5259a5b..27efef7 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -733,8 +733,11 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e
                  * feature for cosmetics, not actually useful for
                  * anything beyond that. */
 
-                if (m->idle_pipe[0] < 0 && m->idle_pipe[1] < 0)
+                if (m->idle_pipe[0] < 0 && m->idle_pipe[1] < 0 &&
+                    m->idle_pipe[2] < 0 && m->idle_pipe[3] < 0) {
                         pipe2(m->idle_pipe, O_NONBLOCK|O_CLOEXEC);
+                        pipe2(m->idle_pipe + 2, O_NONBLOCK|O_CLOEXEC);
+                }
         }
 
         return 0;
diff --git a/src/core/unit.c b/src/core/unit.c
index b245356..f4f92f0 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1425,10 +1425,14 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
         if (UNIT_IS_INACTIVE_OR_FAILED(os) != UNIT_IS_INACTIVE_OR_FAILED(ns)) {
                 ExecContext *ec = unit_get_exec_context(u);
                 if (ec && exec_context_may_touch_console(ec)) {
-                        if (UNIT_IS_INACTIVE_OR_FAILED(ns))
-                                m->n_on_console--;
-                        else
-                                m->n_on_console++;
+                        if (UNIT_IS_INACTIVE_OR_FAILED(ns)) {
+                                m->n_on_console --;
+
+                                if (m->n_on_console == 0)
+                                        /* unset no_console_output flag, since the console is free */
+                                        m->no_console_output = 0;
+                        } else
+                                m->n_on_console ++;
                 }
         }
 

commit 77a9e8de6572db6ba5ca49023937b67fc835f356
Author: Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>
Date:   Mon Jul 15 21:03:17 2013 -0400

    man: add note about paging and colors to journalctl(1)

diff --git a/TODO b/TODO
index 88d9ae6..3fa384c 100644
--- a/TODO
+++ b/TODO
@@ -357,7 +357,7 @@ Features:
   - refuse taking lower-case variable names in sd_journal_send() and friends.
   - journald: we currently rotate only after MaxUse+MaxFilesize has been reached.
   - journal: deal nicely with byte-by-byte copied files, especially regards header
-  - journalctl: show multiline log messages sanely, expand tabs, and show all valid utf8 messages
+  - journalctl: expand tabs
   - journal: store euid in journal if it differs from uid
   - journal: sanely deal with entries which are larger than the individual file size, but where the components would fit
   - Replace utmp, wtmp, btmp, and lastlog completely with journal
diff --git a/man/journalctl.xml b/man/journalctl.xml
index 71b1bab..b8b29b4 100644
--- a/man/journalctl.xml
+++ b/man/journalctl.xml
@@ -107,6 +107,20 @@
                 users who are members of the <literal>adm</literal>
                 group get access to the system journal and the
                 journals of other users.</para>
+
+                <para>The output is paged through
+                <command>less</command> by default, and long lines are
+                "truncated" to screen width. The hidden part can be
+                viewed by using the left-arrow and right-arrow
+                keys. Paging can be disabled, see
+                <option>--no-pager</option> and section Environment
+                below.</para>
+
+                <para>When outputing to a tty, lines are colored
+                according to priority: lines of level ERROR and higher
+                are colored red, lines of level NOTICE and higher are
+                highlighted, and other lines are displayed normally.
+                </para>
         </refsect1>
 
         <refsect1>



More information about the systemd-commits mailing list