[systemd-commits] 2 commits - TODO src/core src/shared

Lennart Poettering lennart at kemper.freedesktop.org
Sat Nov 24 15:34:59 PST 2012


 TODO                 |    9 ----
 src/core/manager.c   |  108 +++++++++++++++++++++++++++++++++++++++++++++------
 src/core/manager.h   |    4 +
 src/core/timer.c     |   13 ++++++
 src/core/unit.h      |    3 +
 src/shared/missing.h |    4 +
 6 files changed, 121 insertions(+), 20 deletions(-)

New commits:
commit 8403cbbe7beb846be6752e1c50c547769a2878f3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Nov 25 00:33:38 2012 +0100

    update TODO

diff --git a/TODO b/TODO
index a9f76de..c99ab6d 100644
--- a/TODO
+++ b/TODO
@@ -19,11 +19,7 @@ F18:
 
 Features:
 
-* reschedule calendar timer events when the time jumps
-
-* kill insserv code
-
-* In parse_timestamp() allow specifying a week day, and if it doesn't match the date, generate a parse failure
+* kill insserv code, people should really use a generator for this
 
 * journald: when dropping msgs due to ratelimit make sure to write
   "dropped %u messages" not only when we are about to print the next
@@ -565,9 +561,6 @@ Features:
 
 * dot output for --test showing the 'initial transaction'
 
-* calendar time support in timer:
-    https://docs.google.com/document/pub?id=1bAMyFAjWLpzR3GTDYdgj5FWRMxoZiWw5zmUHEtvdHKA
-
 * writable cgroups dbus properties for live changes
 
 * port over to LISTEN_FDS/LISTEN_PID:

commit 8742514c1a1a5bc0f423da9101deb66115e187ff
Author: Lennart Poettering <lennart at poettering.net>
Date:   Sun Nov 25 00:32:40 2012 +0100

    timer: recalculate next elapse for calendar timer units when the system clock is changed

diff --git a/src/core/manager.c b/src/core/manager.c
index 72ce2f2..54600c6 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -36,6 +36,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <dirent.h>
+#include <sys/timerfd.h>
 
 #ifdef HAVE_AUDIT
 #include <libaudit.h>
@@ -120,19 +121,61 @@ static int manager_setup_notify(Manager *m) {
         ev.events = EPOLLIN;
         ev.data.ptr = &m->notify_watch;
 
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0)
+        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0) {
+                log_error("Failed to add timer change fd to epoll: %m");
                 return -errno;
+        }
 
         sa.un.sun_path[0] = '@';
         m->notify_socket = strdup(sa.un.sun_path);
         if (!m->notify_socket)
-                return -ENOMEM;
+                return log_oom();
 
         log_debug("Using notification socket %s", m->notify_socket);
 
         return 0;
 }
 
+static int manager_setup_time_change(Manager *m) {
+        struct epoll_event ev;
+        struct itimerspec its;
+
+        assert(m);
+        assert(m->time_change_watch.type == WATCH_INVALID);
+
+        /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever
+         * CLOCK_REALTIME makes a jump relative to CLOCK_MONOTONIC */
+
+        m->time_change_watch.type = WATCH_TIME_CHANGE;
+        m->time_change_watch.fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC);
+        if (m->time_change_watch.fd < 0) {
+                log_error("Failed to create timerfd: %m");
+                return -errno;
+        }
+
+        zero(its);
+        its.it_value.tv_sec = 10000000000; /* Year 2287 or so... */
+        if (timerfd_settime(m->time_change_watch.fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
+                log_debug("Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m");
+                close_nointr_nofail(m->time_change_watch.fd);
+                watch_init(&m->time_change_watch);
+                return 0;
+        }
+
+        zero(ev);
+        ev.events = EPOLLIN;
+        ev.data.ptr = &m->time_change_watch;
+
+        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->time_change_watch.fd, &ev) < 0) {
+                log_error("Failed to add timer change fd to epoll: %m");
+                return -errno;
+        }
+
+        log_debug("Set up TFD_TIMER_CANCEL_ON_SET timerfd.");
+
+        return 0;
+}
+
 static int enable_special_signals(Manager *m) {
         int fd;
 
@@ -208,7 +251,8 @@ static int manager_setup_signals(Manager *m) {
         assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
 
         m->signal_watch.type = WATCH_SIGNAL;
-        if ((m->signal_watch.fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0)
+        m->signal_watch.fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
+        if (m->signal_watch.fd < 0)
                 return -errno;
 
         zero(ev);
@@ -259,7 +303,13 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
         m->pin_cgroupfs_fd = -1;
         m->idle_pipe[0] = m->idle_pipe[1] = -1;
 
-        m->signal_watch.fd = m->mount_watch.fd = m->udev_watch.fd = m->epoll_fd = m->dev_autofs_fd = m->swap_watch.fd = -1;
+        watch_init(&m->signal_watch);
+        watch_init(&m->mount_watch);
+        watch_init(&m->swap_watch);
+        watch_init(&m->udev_watch);
+        watch_init(&m->time_change_watch);
+
+        m->epoll_fd = m->dev_autofs_fd = -1;
         m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
 
         m->environment = strv_copy(environ);
@@ -289,20 +339,29 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
         if (!(m->watch_bus = hashmap_new(string_hash_func, string_compare_func)))
                 goto fail;
 
-        if ((m->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0)
+        m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
+        if (m->epoll_fd < 0)
+                goto fail;
+
+        r = manager_setup_signals(m);
+        if (r < 0)
                 goto fail;
 
-        if ((r = manager_setup_signals(m)) < 0)
+        r = manager_setup_cgroup(m);
+        if (r < 0)
                 goto fail;
 
-        if ((r = manager_setup_cgroup(m)) < 0)
+        r = manager_setup_notify(m);
+        if (r < 0)
                 goto fail;
 
-        if ((r = manager_setup_notify(m)) < 0)
+        r = manager_setup_time_change(m);
+        if (r < 0)
                 goto fail;
 
         /* Try to connect to the busses, if possible. */
-        if ((r = bus_init(m, running_as != SYSTEMD_SYSTEM)) < 0)
+        r = bus_init(m, running_as != SYSTEMD_SYSTEM);
+        if (r < 0)
                 goto fail;
 
         m->taint_usr = dir_is_empty("/usr") > 0;
@@ -487,6 +546,8 @@ void manager_free(Manager *m) {
                 close_nointr_nofail(m->signal_watch.fd);
         if (m->notify_watch.fd >= 0)
                 close_nointr_nofail(m->notify_watch.fd);
+        if (m->time_change_watch.fd >= 0)
+                close_nointr_nofail(m->time_change_watch.fd);
 
         free(m->notify_socket);
 
@@ -1369,6 +1430,7 @@ static int process_event(Manager *m, struct epoll_event *ev) {
                         if (k < 0 && (errno == EINTR || errno == EAGAIN))
                                 break;
 
+                        log_error("Failed to read timer event counter: %s", k < 0 ? strerror(-k) : "Short read");
                         return k < 0 ? -errno : -EIO;
                 }
 
@@ -1402,6 +1464,28 @@ static int process_event(Manager *m, struct epoll_event *ev) {
                 bus_timeout_event(m, w, ev->events);
                 break;
 
+        case WATCH_TIME_CHANGE: {
+                Unit *u;
+                Iterator i;
+
+                log_struct(LOG_INFO,
+                           MESSAGE_ID(SD_MESSAGE_TIME_CHANGE),
+                           "MESSAGE=Time has been changed",
+                           NULL);
+
+                /* Restart the watch */
+                close_nointr_nofail(m->time_change_watch.fd);
+                watch_init(&m->time_change_watch);
+                manager_setup_time_change(m);
+
+                HASHMAP_FOREACH(u, m->units, i) {
+                        if (UNIT_VTABLE(u)->time_change)
+                                UNIT_VTABLE(u)->time_change(u);
+                }
+
+                break;
+        }
+
         default:
                 log_error("event type=%i", w->type);
                 assert_not_reached("Unknown epoll event type.");
@@ -1533,10 +1617,12 @@ int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j) {
         if (!startswith(s, "/org/freedesktop/systemd1/job/"))
                 return -EINVAL;
 
-        if ((r = safe_atou(s + 30, &id)) < 0)
+        r = safe_atou(s + 30, &id);
+        if (r < 0)
                 return r;
 
-        if (!(j = manager_get_job(m, id)))
+        j = manager_get_job(m, id);
+        if (!j)
                 return -ENOENT;
 
         *_j = j;
diff --git a/src/core/manager.h b/src/core/manager.h
index 1644bd6..e9de496 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -60,7 +60,8 @@ enum WatchType {
         WATCH_SWAP,
         WATCH_UDEV,
         WATCH_DBUS_WATCH,
-        WATCH_DBUS_TIMEOUT
+        WATCH_DBUS_TIMEOUT,
+        WATCH_TIME_CHANGE
 };
 
 struct Watch {
@@ -125,6 +126,7 @@ struct Manager {
 
         Watch notify_watch;
         Watch signal_watch;
+        Watch time_change_watch;
 
         int epoll_fd;
 
diff --git a/src/core/timer.c b/src/core/timer.c
index 54c0d0b..bd27970 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -527,6 +527,18 @@ static void timer_reset_failed(Unit *u) {
         t->result = TIMER_SUCCESS;
 }
 
+static void timer_time_change(Unit *u) {
+        Timer *t = TIMER(u);
+
+        assert(u);
+
+        if (t->state != TIMER_WAITING)
+                return;
+
+        log_info("%s: time change, recalculating next elapse.", u->id);
+        timer_enter_waiting(t, false);
+}
+
 static const char* const timer_state_table[_TIMER_STATE_MAX] = {
         [TIMER_DEAD] = "dead",
         [TIMER_WAITING] = "waiting",
@@ -582,6 +594,7 @@ const UnitVTable timer_vtable = {
         .timer_event = timer_timer_event,
 
         .reset_failed = timer_reset_failed,
+        .time_change = timer_time_change,
 
         .bus_interface = "org.freedesktop.systemd1.Timer",
         .bus_message_handler = bus_timer_message_handler,
diff --git a/src/core/unit.h b/src/core/unit.h
index 11804d8..b40f034 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -358,6 +358,9 @@ struct UnitVTable {
         /* Return the set of units that are following each other */
         int (*following_set)(Unit *u, Set **s);
 
+        /* Called whenever CLOCK_REALTIME made a jump */
+        void (*time_change)(Unit *u);
+
         /* This is called for each unit type and should be used to
          * enumerate existing devices and load them. However,
          * everything that is loaded here should still stay in
diff --git a/src/shared/missing.h b/src/shared/missing.h
index 3777cf6..c53579f 100644
--- a/src/shared/missing.h
+++ b/src/shared/missing.h
@@ -253,3 +253,7 @@ static inline int name_to_handle_at(int fd, const char *name, struct file_handle
 #ifndef CIFS_MAGIC_NUMBER
 #define CIFS_MAGIC_NUMBER 0xFF534D42
 #endif
+
+#ifndef TFD_TIMER_CANCEL_ON_SET
+#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
+#endif



More information about the systemd-commits mailing list