]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
journald: add exit on idle
authorLennart Poettering <lennart@poettering.net>
Wed, 27 Nov 2019 13:45:24 +0000 (14:45 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 31 Jan 2020 14:03:44 +0000 (15:03 +0100)
src/journal/journald-server.c
src/journal/journald-server.h
src/journal/journald-stream.c
units/systemd-journald@.service.in

index 5f1faee784233336aa6ab3f370303cbf057407b0..3c2f55941beb056fc409ad00be7e2cea602024c4 100644 (file)
@@ -77,6 +77,8 @@
 
 #define DEFERRED_CLOSES_MAX (4096)
 
+#define IDLE_TIMEOUT_USEC (30*USEC_PER_SEC)
+
 static int determine_path_usage(
                 Server *s,
                 const char *path,
@@ -1216,6 +1218,7 @@ finish:
         if (k < 0)
                 log_warning_errno(k, "Failed to touch %s, ignoring: %m", fn);
 
+        server_refresh_idle_timer(s);
         return r;
 }
 
@@ -1244,10 +1247,16 @@ static int server_relinquish_var(Server *s) {
         if (unlink(fn) < 0 && errno != ENOENT)
                 log_warning_errno(errno, "Failed to unlink %s, ignoring: %m", fn);
 
+        server_refresh_idle_timer(s);
         return 0;
 }
 
-int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
+int server_process_datagram(
+                sd_event_source *es,
+                int fd,
+                uint32_t revents,
+                void *userdata) {
+
         Server *s = userdata;
         struct ucred *ucred = NULL;
         struct timeval *tv = NULL;
@@ -1362,6 +1371,8 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
         }
 
         close_many(fds, n_fds);
+
+        server_refresh_idle_timer(s);
         return 0;
 }
 
@@ -1373,6 +1384,8 @@ static void server_full_flush(Server *s) {
         server_vacuum(s, false);
 
         server_space_usage_message(s, NULL);
+
+        server_refresh_idle_timer(s);
 }
 
 static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
@@ -2001,6 +2014,28 @@ static int vl_method_relinquish_var(Varlink *link, JsonVariant *parameters, Varl
         return varlink_reply(link, NULL);
 }
 
+static int vl_connect(VarlinkServer *server, Varlink *link, void *userdata) {
+        Server *s = userdata;
+
+        assert(server);
+        assert(link);
+        assert(s);
+
+        (void) server_start_or_stop_idle_timer(s); /* maybe we are no longer idle */
+
+        return 0;
+}
+
+static void vl_disconnect(VarlinkServer *server, Varlink *link, void *userdata) {
+        Server *s = userdata;
+
+        assert(server);
+        assert(link);
+        assert(s);
+
+        (void) server_start_or_stop_idle_timer(s); /* maybe we are idle now */
+}
+
 static int server_open_varlink(Server *s) {
         const char *fn;
         int r;
@@ -2022,6 +2057,14 @@ static int server_open_varlink(Server *s) {
         if (r < 0)
                 return r;
 
+        r = varlink_server_bind_connect(s->varlink_server, vl_connect);
+        if (r < 0)
+                return r;
+
+        r = varlink_server_bind_disconnect(s->varlink_server, vl_disconnect);
+        if (r < 0)
+                return r;
+
         fn = strjoina(s->runtime_directory, "/io.systemd.journal");
 
         r = varlink_server_listen_address(s->varlink_server, fn, 0600);
@@ -2035,6 +2078,93 @@ static int server_open_varlink(Server *s) {
         return 0;
 }
 
+static bool server_is_idle(Server *s) {
+        assert(s);
+
+        /* The server for the main namespace is never idle */
+        if (!s->namespace)
+                return false;
+
+        /* If a retention maximum is set larger than the idle time we need to be running to enforce it, hence
+         * turn off the idle logic. */
+        if (s->max_retention_usec > IDLE_TIMEOUT_USEC)
+                return false;
+
+        /* We aren't idle if we have a varlink client */
+        if (varlink_server_current_connections(s->varlink_server) > 0)
+                return false;
+
+        /* If we have stdout streams we aren't idle */
+        if (s->n_stdout_streams > 0)
+                return false;
+
+        return true;
+}
+
+static int server_idle_handler(sd_event_source *source, uint64_t usec, void *userdata) {
+        Server *s = userdata;
+
+        assert(source);
+        assert(s);
+
+        log_debug("Server is idle, exiting.");
+        sd_event_exit(s->event, 0);
+        return 0;
+}
+
+int server_start_or_stop_idle_timer(Server *s) {
+        _cleanup_(sd_event_source_unrefp) sd_event_source *source = NULL;
+        usec_t when;
+        int r;
+
+        assert(s);
+
+        if (!server_is_idle(s)) {
+                s->idle_event_source = sd_event_source_disable_unref(s->idle_event_source);
+                return 0;
+        }
+
+        if (s->idle_event_source)
+                return 1;
+
+        r = sd_event_now(s->event, CLOCK_MONOTONIC, &when);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine current time: %m");
+
+        r = sd_event_add_time(s->event, &source, CLOCK_MONOTONIC, usec_add(when, IDLE_TIMEOUT_USEC), 0, server_idle_handler, s);
+        if (r < 0)
+                return log_error_errno(r, "Failed to allocate idle timer: %m");
+
+        r = sd_event_source_set_priority(source, SD_EVENT_PRIORITY_IDLE);
+        if (r < 0)
+                return log_error_errno(r, "Failed to set idle timer priority: %m");
+
+        (void) sd_event_source_set_description(source, "idle-timer");
+
+        s->idle_event_source = TAKE_PTR(source);
+        return 1;
+}
+
+int server_refresh_idle_timer(Server *s) {
+        usec_t when;
+        int r;
+
+        assert(s);
+
+        if (!s->idle_event_source)
+                return 0;
+
+        r = sd_event_now(s->event, CLOCK_MONOTONIC, &when);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine current time: %m");
+
+        r = sd_event_source_set_time(s->idle_event_source, usec_add(when, IDLE_TIMEOUT_USEC));
+        if (r < 0)
+                return log_error_errno(r, "Failed to refresh idle timer: %m");
+
+        return 1;
+}
+
 static int set_namespace(Server *s, const char *namespace) {
         assert(s);
 
@@ -2298,7 +2428,12 @@ int server_init(Server *s, const char *namespace) {
 
         (void) client_context_acquire_default(s);
 
-        return system_journal_open(s, false, false);
+        r = system_journal_open(s, false, false);
+        if (r < 0)
+                return r;
+
+        server_start_or_stop_idle_timer(s);
+        return 0;
 }
 
 void server_maybe_append_tags(Server *s) {
@@ -2351,6 +2486,7 @@ void server_done(Server *s) {
         sd_event_source_unref(s->hostname_event_source);
         sd_event_source_unref(s->notify_event_source);
         sd_event_source_unref(s->watchdog_event_source);
+        sd_event_source_unref(s->idle_event_source);
         sd_event_unref(s->event);
 
         safe_close(s->syslog_fd);
index 812c1eca8db95460e3c076215d892ecf9b063b81..f3405e967cd0fbd357d7dc003722d461fd6ad6f7 100644 (file)
@@ -86,6 +86,7 @@ struct Server {
         sd_event_source *hostname_event_source;
         sd_event_source *notify_event_source;
         sd_event_source *watchdog_event_source;
+        sd_event_source *idle_event_source;
 
         JournalFile *runtime_journal;
         JournalFile *system_journal;
@@ -218,3 +219,6 @@ int server_flush_to_var(Server *s, bool require_flag_file);
 void server_maybe_append_tags(Server *s);
 int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata);
 void server_space_usage_message(Server *s, JournalStorage *storage);
+
+int server_start_or_stop_idle_timer(Server *s);
+int server_refresh_idle_timer(Server *s);
index 7905887152a0d160f0e87a0d46dfd18aca7889ac..d5147cb61a4acf69ce1f065173b8f275a0539a3a 100644 (file)
@@ -110,6 +110,8 @@ void stdout_stream_free(StdoutStream *s) {
 
                 if (s->in_notify_queue)
                         LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
+
+                (void) server_start_or_stop_idle_timer(s->server); /* Maybe we are idle now? */
         }
 
         if (s->event_source) {
@@ -631,6 +633,8 @@ int stdout_stream_install(Server *s, int fd, StdoutStream **ret) {
         LIST_PREPEND(stdout_stream, s->stdout_streams, stream);
         s->n_stdout_streams++;
 
+        (void) server_start_or_stop_idle_timer(s); /* Maybe no longer idle? */
+
         if (ret)
                 *ret = stream;
 
index e7274925a9d8218f3bae7b04fa5b98c4d54405fc..43082fa41b8e505490d5d3b412804b8c2a53e172 100644 (file)
@@ -25,8 +25,6 @@ LogsDirectory=journal/%m.%i
 LogsDirectoryMode=02755
 MemoryDenyWriteExecute=yes
 NoNewPrivileges=yes
-Restart=always
-RestartSec=0
 RestrictAddressFamilies=AF_UNIX AF_NETLINK
 RestrictNamespaces=yes
 RestrictRealtime=yes