LCOV - code coverage report
Current view: top level - core - timer.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 2 458 0.4 %
Date: 2019-08-22 15:41:25 Functions: 4 33 12.1 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <sys/stat.h>
       4             : #include <sys/types.h>
       5             : #include <unistd.h>
       6             : 
       7             : #include <errno.h>
       8             : 
       9             : #include "alloc-util.h"
      10             : #include "bus-error.h"
      11             : #include "bus-util.h"
      12             : #include "dbus-timer.h"
      13             : #include "dbus-unit.h"
      14             : #include "fs-util.h"
      15             : #include "parse-util.h"
      16             : #include "random-util.h"
      17             : #include "serialize.h"
      18             : #include "special.h"
      19             : #include "string-table.h"
      20             : #include "string-util.h"
      21             : #include "timer.h"
      22             : #include "unit-name.h"
      23             : #include "unit.h"
      24             : #include "user-util.h"
      25             : #include "virt.h"
      26             : 
      27             : static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
      28             :         [TIMER_DEAD] = UNIT_INACTIVE,
      29             :         [TIMER_WAITING] = UNIT_ACTIVE,
      30             :         [TIMER_RUNNING] = UNIT_ACTIVE,
      31             :         [TIMER_ELAPSED] = UNIT_ACTIVE,
      32             :         [TIMER_FAILED] = UNIT_FAILED
      33             : };
      34             : 
      35             : static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata);
      36             : 
      37           0 : static void timer_init(Unit *u) {
      38           0 :         Timer *t = TIMER(u);
      39             : 
      40           0 :         assert(u);
      41           0 :         assert(u->load_state == UNIT_STUB);
      42             : 
      43           0 :         t->next_elapse_monotonic_or_boottime = USEC_INFINITY;
      44           0 :         t->next_elapse_realtime = USEC_INFINITY;
      45           0 :         t->accuracy_usec = u->manager->default_timer_accuracy_usec;
      46           0 :         t->remain_after_elapse = true;
      47           0 : }
      48             : 
      49           0 : void timer_free_values(Timer *t) {
      50             :         TimerValue *v;
      51             : 
      52           0 :         assert(t);
      53             : 
      54           0 :         while ((v = t->values)) {
      55           0 :                 LIST_REMOVE(value, t->values, v);
      56           0 :                 calendar_spec_free(v->calendar_spec);
      57           0 :                 free(v);
      58             :         }
      59           0 : }
      60             : 
      61           0 : static void timer_done(Unit *u) {
      62           0 :         Timer *t = TIMER(u);
      63             : 
      64           0 :         assert(t);
      65             : 
      66           0 :         timer_free_values(t);
      67             : 
      68           0 :         t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
      69           0 :         t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
      70             : 
      71           0 :         free(t->stamp_path);
      72           0 : }
      73             : 
      74           0 : static int timer_verify(Timer *t) {
      75           0 :         assert(t);
      76             : 
      77           0 :         if (UNIT(t)->load_state != UNIT_LOADED)
      78           0 :                 return 0;
      79             : 
      80           0 :         if (!t->values && !t->on_clock_change && !t->on_timezone_change) {
      81           0 :                 log_unit_error(UNIT(t), "Timer unit lacks value setting. Refusing.");
      82           0 :                 return -ENOEXEC;
      83             :         }
      84             : 
      85           0 :         return 0;
      86             : }
      87             : 
      88           0 : static int timer_add_default_dependencies(Timer *t) {
      89             :         int r;
      90             :         TimerValue *v;
      91             : 
      92           0 :         assert(t);
      93             : 
      94           0 :         if (!UNIT(t)->default_dependencies)
      95           0 :                 return 0;
      96             : 
      97           0 :         r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_TIMERS_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
      98           0 :         if (r < 0)
      99           0 :                 return r;
     100             : 
     101           0 :         if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) {
     102           0 :                 r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
     103           0 :                 if (r < 0)
     104           0 :                         return r;
     105             : 
     106           0 :                 LIST_FOREACH(value, v, t->values) {
     107           0 :                         if (v->base == TIMER_CALENDAR) {
     108           0 :                                 r = unit_add_dependency_by_name(UNIT(t), UNIT_AFTER, SPECIAL_TIME_SYNC_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
     109           0 :                                 if (r < 0)
     110           0 :                                         return r;
     111           0 :                                 break;
     112             :                         }
     113             :                 }
     114             :         }
     115             : 
     116           0 :         return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
     117             : }
     118             : 
     119           0 : static int timer_add_trigger_dependencies(Timer *t) {
     120             :         Unit *x;
     121             :         int r;
     122             : 
     123           0 :         assert(t);
     124             : 
     125           0 :         if (!hashmap_isempty(UNIT(t)->dependencies[UNIT_TRIGGERS]))
     126           0 :                 return 0;
     127             : 
     128           0 :         r = unit_load_related_unit(UNIT(t), ".service", &x);
     129           0 :         if (r < 0)
     130           0 :                 return r;
     131             : 
     132           0 :         return unit_add_two_dependencies(UNIT(t), UNIT_BEFORE, UNIT_TRIGGERS, x, true, UNIT_DEPENDENCY_IMPLICIT);
     133             : }
     134             : 
     135           0 : static int timer_setup_persistent(Timer *t) {
     136             :         int r;
     137             : 
     138           0 :         assert(t);
     139             : 
     140           0 :         if (!t->persistent)
     141           0 :                 return 0;
     142             : 
     143           0 :         if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) {
     144             : 
     145           0 :                 r = unit_require_mounts_for(UNIT(t), "/var/lib/systemd/timers", UNIT_DEPENDENCY_FILE);
     146           0 :                 if (r < 0)
     147           0 :                         return r;
     148             : 
     149           0 :                 t->stamp_path = strjoin("/var/lib/systemd/timers/stamp-", UNIT(t)->id);
     150             :         } else {
     151             :                 const char *e;
     152             : 
     153           0 :                 e = getenv("XDG_DATA_HOME");
     154           0 :                 if (e)
     155           0 :                         t->stamp_path = strjoin(e, "/systemd/timers/stamp-", UNIT(t)->id);
     156             :                 else {
     157             : 
     158           0 :                         _cleanup_free_ char *h = NULL;
     159             : 
     160           0 :                         r = get_home_dir(&h);
     161           0 :                         if (r < 0)
     162           0 :                                 return log_unit_error_errno(UNIT(t), r, "Failed to determine home directory: %m");
     163             : 
     164           0 :                         t->stamp_path = strjoin(h, "/.local/share/systemd/timers/stamp-", UNIT(t)->id);
     165             :                 }
     166             :         }
     167             : 
     168           0 :         if (!t->stamp_path)
     169           0 :                 return log_oom();
     170             : 
     171           0 :         return 0;
     172             : }
     173             : 
     174           0 : static int timer_load(Unit *u) {
     175           0 :         Timer *t = TIMER(u);
     176             :         int r;
     177             : 
     178           0 :         assert(u);
     179           0 :         assert(u->load_state == UNIT_STUB);
     180             : 
     181           0 :         r = unit_load_fragment_and_dropin(u);
     182           0 :         if (r < 0)
     183           0 :                 return r;
     184             : 
     185           0 :         if (u->load_state == UNIT_LOADED) {
     186             : 
     187           0 :                 r = timer_add_trigger_dependencies(t);
     188           0 :                 if (r < 0)
     189           0 :                         return r;
     190             : 
     191           0 :                 r = timer_setup_persistent(t);
     192           0 :                 if (r < 0)
     193           0 :                         return r;
     194             : 
     195           0 :                 r = timer_add_default_dependencies(t);
     196           0 :                 if (r < 0)
     197           0 :                         return r;
     198             :         }
     199             : 
     200           0 :         return timer_verify(t);
     201             : }
     202             : 
     203           0 : static void timer_dump(Unit *u, FILE *f, const char *prefix) {
     204             :         char buf[FORMAT_TIMESPAN_MAX];
     205           0 :         Timer *t = TIMER(u);
     206             :         Unit *trigger;
     207             :         TimerValue *v;
     208             : 
     209           0 :         trigger = UNIT_TRIGGER(u);
     210             : 
     211           0 :         fprintf(f,
     212             :                 "%sTimer State: %s\n"
     213             :                 "%sResult: %s\n"
     214             :                 "%sUnit: %s\n"
     215             :                 "%sPersistent: %s\n"
     216             :                 "%sWakeSystem: %s\n"
     217             :                 "%sAccuracy: %s\n"
     218             :                 "%sRemainAfterElapse: %s\n"
     219             :                 "%sOnClockChange: %s\n"
     220             :                 "%sOnTimeZoneChange %s\n",
     221             :                 prefix, timer_state_to_string(t->state),
     222             :                 prefix, timer_result_to_string(t->result),
     223             :                 prefix, trigger ? trigger->id : "n/a",
     224           0 :                 prefix, yes_no(t->persistent),
     225           0 :                 prefix, yes_no(t->wake_system),
     226             :                 prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1),
     227           0 :                 prefix, yes_no(t->remain_after_elapse),
     228           0 :                 prefix, yes_no(t->on_clock_change),
     229           0 :                 prefix, yes_no(t->on_timezone_change));
     230             : 
     231           0 :         LIST_FOREACH(value, v, t->values) {
     232             : 
     233           0 :                 if (v->base == TIMER_CALENDAR) {
     234           0 :                         _cleanup_free_ char *p = NULL;
     235             : 
     236           0 :                         (void) calendar_spec_to_string(v->calendar_spec, &p);
     237             : 
     238           0 :                         fprintf(f,
     239             :                                 "%s%s: %s\n",
     240             :                                 prefix,
     241             :                                 timer_base_to_string(v->base),
     242             :                                 strna(p));
     243             :                 } else  {
     244             :                         char timespan1[FORMAT_TIMESPAN_MAX];
     245             : 
     246           0 :                         fprintf(f,
     247             :                                 "%s%s: %s\n",
     248             :                                 prefix,
     249             :                                 timer_base_to_string(v->base),
     250             :                                 format_timespan(timespan1, sizeof(timespan1), v->value, 0));
     251             :                 }
     252             :         }
     253           0 : }
     254             : 
     255           0 : static void timer_set_state(Timer *t, TimerState state) {
     256             :         TimerState old_state;
     257           0 :         assert(t);
     258             : 
     259           0 :         if (t->state != state)
     260           0 :                 bus_unit_send_pending_change_signal(UNIT(t), false);
     261             : 
     262           0 :         old_state = t->state;
     263           0 :         t->state = state;
     264             : 
     265           0 :         if (state != TIMER_WAITING) {
     266           0 :                 t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
     267           0 :                 t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
     268           0 :                 t->next_elapse_monotonic_or_boottime = USEC_INFINITY;
     269           0 :                 t->next_elapse_realtime = USEC_INFINITY;
     270             :         }
     271             : 
     272           0 :         if (state != old_state)
     273           0 :                 log_unit_debug(UNIT(t), "Changed %s -> %s", timer_state_to_string(old_state), timer_state_to_string(state));
     274             : 
     275           0 :         unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
     276           0 : }
     277             : 
     278             : static void timer_enter_waiting(Timer *t, bool time_change);
     279             : 
     280           0 : static int timer_coldplug(Unit *u) {
     281           0 :         Timer *t = TIMER(u);
     282             : 
     283           0 :         assert(t);
     284           0 :         assert(t->state == TIMER_DEAD);
     285             : 
     286           0 :         if (t->deserialized_state == t->state)
     287           0 :                 return 0;
     288             : 
     289           0 :         if (t->deserialized_state == TIMER_WAITING)
     290           0 :                 timer_enter_waiting(t, false);
     291             :         else
     292           0 :                 timer_set_state(t, t->deserialized_state);
     293             : 
     294           0 :         return 0;
     295             : }
     296             : 
     297           0 : static void timer_enter_dead(Timer *t, TimerResult f) {
     298           0 :         assert(t);
     299             : 
     300           0 :         if (t->result == TIMER_SUCCESS)
     301           0 :                 t->result = f;
     302             : 
     303           0 :         unit_log_result(UNIT(t), t->result == TIMER_SUCCESS, timer_result_to_string(t->result));
     304           0 :         timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
     305           0 : }
     306             : 
     307           0 : static void timer_enter_elapsed(Timer *t, bool leave_around) {
     308           0 :         assert(t);
     309             : 
     310             :         /* If a unit is marked with RemainAfterElapse=yes we leave it
     311             :          * around even after it elapsed once, so that starting it
     312             :          * later again does not necessarily mean immediate
     313             :          * retriggering. We unconditionally leave units with
     314             :          * TIMER_UNIT_ACTIVE or TIMER_UNIT_INACTIVE triggers around,
     315             :          * since they might be restarted automatically at any time
     316             :          * later on. */
     317             : 
     318           0 :         if (t->remain_after_elapse || leave_around)
     319           0 :                 timer_set_state(t, TIMER_ELAPSED);
     320             :         else
     321           0 :                 timer_enter_dead(t, TIMER_SUCCESS);
     322           0 : }
     323             : 
     324           0 : static void add_random(Timer *t, usec_t *v) {
     325             :         char s[FORMAT_TIMESPAN_MAX];
     326             :         usec_t add;
     327             : 
     328           0 :         assert(t);
     329           0 :         assert(v);
     330             : 
     331           0 :         if (t->random_usec == 0)
     332           0 :                 return;
     333           0 :         if (*v == USEC_INFINITY)
     334           0 :                 return;
     335             : 
     336           0 :         add = random_u64() % t->random_usec;
     337             : 
     338           0 :         if (*v + add < *v) /* overflow */
     339           0 :                 *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */
     340             :         else
     341           0 :                 *v += add;
     342             : 
     343           0 :         log_unit_debug(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0));
     344             : }
     345             : 
     346           0 : static void timer_enter_waiting(Timer *t, bool time_change) {
     347           0 :         bool found_monotonic = false, found_realtime = false;
     348           0 :         bool leave_around = false;
     349             :         triple_timestamp ts;
     350             :         TimerValue *v;
     351             :         Unit *trigger;
     352             :         int r;
     353             : 
     354           0 :         assert(t);
     355             : 
     356           0 :         trigger = UNIT_TRIGGER(UNIT(t));
     357           0 :         if (!trigger) {
     358           0 :                 log_unit_error(UNIT(t), "Unit to trigger vanished.");
     359           0 :                 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
     360           0 :                 return;
     361             :         }
     362             : 
     363           0 :         triple_timestamp_get(&ts);
     364           0 :         t->next_elapse_monotonic_or_boottime = t->next_elapse_realtime = 0;
     365             : 
     366           0 :         LIST_FOREACH(value, v, t->values) {
     367           0 :                 if (v->disabled)
     368           0 :                         continue;
     369             : 
     370           0 :                 if (v->base == TIMER_CALENDAR) {
     371             :                         usec_t b;
     372             : 
     373             :                         /* If we know the last time this was
     374             :                          * triggered, schedule the job based relative
     375             :                          * to that. If we don't, just start from
     376             :                          * the activation time. */
     377             : 
     378           0 :                         if (t->last_trigger.realtime > 0)
     379           0 :                                 b = t->last_trigger.realtime;
     380             :                         else {
     381           0 :                                 if (state_translation_table[t->state] == UNIT_ACTIVE)
     382           0 :                                         b = UNIT(t)->inactive_exit_timestamp.realtime;
     383             :                                 else
     384           0 :                                         b = ts.realtime;
     385             :                         }
     386             : 
     387           0 :                         r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
     388           0 :                         if (r < 0)
     389           0 :                                 continue;
     390             : 
     391             :                         /* To make the delay due to RandomizedDelaySec= work even at boot,
     392             :                          * if the scheduled time has already passed, set the time when systemd
     393             :                          * first started as the scheduled time.
     394             :                          * Also, we don't have to check t->persistent since the logic implicitly express true. */
     395           0 :                         if (v->next_elapse < UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].realtime)
     396           0 :                                 v->next_elapse = UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].realtime;
     397             : 
     398           0 :                         if (!found_realtime)
     399           0 :                                 t->next_elapse_realtime = v->next_elapse;
     400             :                         else
     401           0 :                                 t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse);
     402             : 
     403           0 :                         found_realtime = true;
     404             : 
     405             :                 } else {
     406             :                         usec_t base;
     407             : 
     408           0 :                         switch (v->base) {
     409             : 
     410           0 :                         case TIMER_ACTIVE:
     411           0 :                                 if (state_translation_table[t->state] == UNIT_ACTIVE)
     412           0 :                                         base = UNIT(t)->inactive_exit_timestamp.monotonic;
     413             :                                 else
     414           0 :                                         base = ts.monotonic;
     415           0 :                                 break;
     416             : 
     417           0 :                         case TIMER_BOOT:
     418           0 :                                 if (detect_container() <= 0) {
     419             :                                         /* CLOCK_MONOTONIC equals the uptime on Linux */
     420           0 :                                         base = 0;
     421           0 :                                         break;
     422             :                                 }
     423             :                                 /* In a container we don't want to include the time the host
     424             :                                  * was already up when the container started, so count from
     425             :                                  * our own startup. */
     426             :                                 _fallthrough_;
     427             :                         case TIMER_STARTUP:
     428           0 :                                 base = UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic;
     429           0 :                                 break;
     430             : 
     431           0 :                         case TIMER_UNIT_ACTIVE:
     432           0 :                                 leave_around = true;
     433           0 :                                 base = MAX(trigger->inactive_exit_timestamp.monotonic, t->last_trigger.monotonic);
     434           0 :                                 if (base <= 0)
     435           0 :                                         continue;
     436           0 :                                 break;
     437             : 
     438           0 :                         case TIMER_UNIT_INACTIVE:
     439           0 :                                 leave_around = true;
     440           0 :                                 base = MAX(trigger->inactive_enter_timestamp.monotonic, t->last_trigger.monotonic);
     441           0 :                                 if (base <= 0)
     442           0 :                                         continue;
     443           0 :                                 break;
     444             : 
     445           0 :                         default:
     446           0 :                                 assert_not_reached("Unknown timer base");
     447             :                         }
     448             : 
     449           0 :                         v->next_elapse = usec_add(usec_shift_clock(base, CLOCK_MONOTONIC, TIMER_MONOTONIC_CLOCK(t)), v->value);
     450             : 
     451           0 :                         if (dual_timestamp_is_set(&t->last_trigger) &&
     452           0 :                             !time_change &&
     453           0 :                             v->next_elapse < triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)) &&
     454           0 :                             IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
     455             :                                 /* This is a one time trigger, disable it now */
     456           0 :                                 v->disabled = true;
     457           0 :                                 continue;
     458             :                         }
     459             : 
     460           0 :                         if (!found_monotonic)
     461           0 :                                 t->next_elapse_monotonic_or_boottime = v->next_elapse;
     462             :                         else
     463           0 :                                 t->next_elapse_monotonic_or_boottime = MIN(t->next_elapse_monotonic_or_boottime, v->next_elapse);
     464             : 
     465           0 :                         found_monotonic = true;
     466             :                 }
     467             :         }
     468             : 
     469           0 :         if (!found_monotonic && !found_realtime && !t->on_timezone_change && !t->on_clock_change) {
     470           0 :                 log_unit_debug(UNIT(t), "Timer is elapsed.");
     471           0 :                 timer_enter_elapsed(t, leave_around);
     472           0 :                 return;
     473             :         }
     474             : 
     475           0 :         if (found_monotonic) {
     476             :                 char buf[FORMAT_TIMESPAN_MAX];
     477             :                 usec_t left;
     478             : 
     479           0 :                 add_random(t, &t->next_elapse_monotonic_or_boottime);
     480             : 
     481           0 :                 left = usec_sub_unsigned(t->next_elapse_monotonic_or_boottime, triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)));
     482           0 :                 log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), left, 0));
     483             : 
     484           0 :                 if (t->monotonic_event_source) {
     485           0 :                         r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic_or_boottime);
     486           0 :                         if (r < 0)
     487           0 :                                 goto fail;
     488             : 
     489           0 :                         r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
     490           0 :                         if (r < 0)
     491           0 :                                 goto fail;
     492             :                 } else {
     493             : 
     494           0 :                         r = sd_event_add_time(
     495           0 :                                         UNIT(t)->manager->event,
     496             :                                         &t->monotonic_event_source,
     497           0 :                                         t->wake_system ? CLOCK_BOOTTIME_ALARM : CLOCK_MONOTONIC,
     498             :                                         t->next_elapse_monotonic_or_boottime, t->accuracy_usec,
     499             :                                         timer_dispatch, t);
     500           0 :                         if (r < 0)
     501           0 :                                 goto fail;
     502             : 
     503           0 :                         (void) sd_event_source_set_description(t->monotonic_event_source, "timer-monotonic");
     504             :                 }
     505             : 
     506           0 :         } else if (t->monotonic_event_source) {
     507             : 
     508           0 :                 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
     509           0 :                 if (r < 0)
     510           0 :                         goto fail;
     511             :         }
     512             : 
     513           0 :         if (found_realtime) {
     514             :                 char buf[FORMAT_TIMESTAMP_MAX];
     515             : 
     516           0 :                 add_random(t, &t->next_elapse_realtime);
     517             : 
     518           0 :                 log_unit_debug(UNIT(t), "Realtime timer elapses at %s.", format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
     519             : 
     520           0 :                 if (t->realtime_event_source) {
     521           0 :                         r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
     522           0 :                         if (r < 0)
     523           0 :                                 goto fail;
     524             : 
     525           0 :                         r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
     526           0 :                         if (r < 0)
     527           0 :                                 goto fail;
     528             :                 } else {
     529           0 :                         r = sd_event_add_time(
     530           0 :                                         UNIT(t)->manager->event,
     531             :                                         &t->realtime_event_source,
     532           0 :                                         t->wake_system ? CLOCK_REALTIME_ALARM : CLOCK_REALTIME,
     533             :                                         t->next_elapse_realtime, t->accuracy_usec,
     534             :                                         timer_dispatch, t);
     535           0 :                         if (r < 0)
     536           0 :                                 goto fail;
     537             : 
     538           0 :                         (void) sd_event_source_set_description(t->realtime_event_source, "timer-realtime");
     539             :                 }
     540             : 
     541           0 :         } else if (t->realtime_event_source) {
     542             : 
     543           0 :                 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
     544           0 :                 if (r < 0)
     545           0 :                         goto fail;
     546             :         }
     547             : 
     548           0 :         timer_set_state(t, TIMER_WAITING);
     549           0 :         return;
     550             : 
     551           0 : fail:
     552           0 :         log_unit_warning_errno(UNIT(t), r, "Failed to enter waiting state: %m");
     553           0 :         timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
     554             : }
     555             : 
     556           0 : static void timer_enter_running(Timer *t) {
     557           0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     558             :         Unit *trigger;
     559             :         int r;
     560             : 
     561           0 :         assert(t);
     562             : 
     563             :         /* Don't start job if we are supposed to go down */
     564           0 :         if (unit_stop_pending(UNIT(t)))
     565           0 :                 return;
     566             : 
     567           0 :         trigger = UNIT_TRIGGER(UNIT(t));
     568           0 :         if (!trigger) {
     569           0 :                 log_unit_error(UNIT(t), "Unit to trigger vanished.");
     570           0 :                 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
     571           0 :                 return;
     572             :         }
     573             : 
     574           0 :         r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
     575           0 :         if (r < 0)
     576           0 :                 goto fail;
     577             : 
     578           0 :         dual_timestamp_get(&t->last_trigger);
     579             : 
     580           0 :         if (t->stamp_path)
     581           0 :                 touch_file(t->stamp_path, true, t->last_trigger.realtime, UID_INVALID, GID_INVALID, MODE_INVALID);
     582             : 
     583           0 :         timer_set_state(t, TIMER_RUNNING);
     584           0 :         return;
     585             : 
     586           0 : fail:
     587           0 :         log_unit_warning(UNIT(t), "Failed to queue unit startup job: %s", bus_error_message(&error, r));
     588           0 :         timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
     589             : }
     590             : 
     591           0 : static int timer_start(Unit *u) {
     592           0 :         Timer *t = TIMER(u);
     593             :         TimerValue *v;
     594             :         int r;
     595             : 
     596           0 :         assert(t);
     597           0 :         assert(IN_SET(t->state, TIMER_DEAD, TIMER_FAILED));
     598             : 
     599           0 :         r = unit_test_trigger_loaded(u);
     600           0 :         if (r < 0)
     601           0 :                 return r;
     602             : 
     603           0 :         r = unit_test_start_limit(u);
     604           0 :         if (r < 0) {
     605           0 :                 timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT);
     606           0 :                 return r;
     607             :         }
     608             : 
     609           0 :         r = unit_acquire_invocation_id(u);
     610           0 :         if (r < 0)
     611           0 :                 return r;
     612             : 
     613           0 :         t->last_trigger = DUAL_TIMESTAMP_NULL;
     614             : 
     615             :         /* Reenable all timers that depend on unit activation time */
     616           0 :         LIST_FOREACH(value, v, t->values)
     617           0 :                 if (v->base == TIMER_ACTIVE)
     618           0 :                         v->disabled = false;
     619             : 
     620           0 :         if (t->stamp_path) {
     621             :                 struct stat st;
     622             : 
     623           0 :                 if (stat(t->stamp_path, &st) >= 0) {
     624             :                         usec_t ft;
     625             : 
     626             :                         /* Load the file timestamp, but only if it is actually in the past. If it is in the future,
     627             :                          * something is wrong with the system clock. */
     628             : 
     629           0 :                         ft = timespec_load(&st.st_mtim);
     630           0 :                         if (ft < now(CLOCK_REALTIME))
     631           0 :                                 t->last_trigger.realtime = ft;
     632             :                         else {
     633             :                                 char z[FORMAT_TIMESTAMP_MAX];
     634             : 
     635           0 :                                 log_unit_warning(u, "Not using persistent file timestamp %s as it is in the future.",
     636             :                                                  format_timestamp(z, sizeof(z), ft));
     637             :                         }
     638             : 
     639           0 :                 } else if (errno == ENOENT)
     640             :                         /* The timer has never run before,
     641             :                          * make sure a stamp file exists.
     642             :                          */
     643           0 :                         (void) touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
     644             :         }
     645             : 
     646           0 :         t->result = TIMER_SUCCESS;
     647           0 :         timer_enter_waiting(t, false);
     648           0 :         return 1;
     649             : }
     650             : 
     651           0 : static int timer_stop(Unit *u) {
     652           0 :         Timer *t = TIMER(u);
     653             : 
     654           0 :         assert(t);
     655           0 :         assert(IN_SET(t->state, TIMER_WAITING, TIMER_RUNNING, TIMER_ELAPSED));
     656             : 
     657           0 :         timer_enter_dead(t, TIMER_SUCCESS);
     658           0 :         return 1;
     659             : }
     660             : 
     661           0 : static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
     662           0 :         Timer *t = TIMER(u);
     663             : 
     664           0 :         assert(u);
     665           0 :         assert(f);
     666           0 :         assert(fds);
     667             : 
     668           0 :         (void) serialize_item(f, "state", timer_state_to_string(t->state));
     669           0 :         (void) serialize_item(f, "result", timer_result_to_string(t->result));
     670             : 
     671           0 :         if (t->last_trigger.realtime > 0)
     672           0 :                 (void) serialize_usec(f, "last-trigger-realtime", t->last_trigger.realtime);
     673             : 
     674           0 :         if (t->last_trigger.monotonic > 0)
     675           0 :                 (void) serialize_usec(f, "last-trigger-monotonic", t->last_trigger.monotonic);
     676             : 
     677           0 :         return 0;
     678             : }
     679             : 
     680           0 : static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
     681           0 :         Timer *t = TIMER(u);
     682             : 
     683           0 :         assert(u);
     684           0 :         assert(key);
     685           0 :         assert(value);
     686           0 :         assert(fds);
     687             : 
     688           0 :         if (streq(key, "state")) {
     689             :                 TimerState state;
     690             : 
     691           0 :                 state = timer_state_from_string(value);
     692           0 :                 if (state < 0)
     693           0 :                         log_unit_debug(u, "Failed to parse state value: %s", value);
     694             :                 else
     695           0 :                         t->deserialized_state = state;
     696             : 
     697           0 :         } else if (streq(key, "result")) {
     698             :                 TimerResult f;
     699             : 
     700           0 :                 f = timer_result_from_string(value);
     701           0 :                 if (f < 0)
     702           0 :                         log_unit_debug(u, "Failed to parse result value: %s", value);
     703           0 :                 else if (f != TIMER_SUCCESS)
     704           0 :                         t->result = f;
     705             : 
     706           0 :         } else if (streq(key, "last-trigger-realtime"))
     707           0 :                 (void) deserialize_usec(value, &t->last_trigger.realtime);
     708           0 :         else if (streq(key, "last-trigger-monotonic"))
     709           0 :                 (void) deserialize_usec(value, &t->last_trigger.monotonic);
     710             :         else
     711           0 :                 log_unit_debug(u, "Unknown serialization key: %s", key);
     712             : 
     713           0 :         return 0;
     714             : }
     715             : 
     716           0 : _pure_ static UnitActiveState timer_active_state(Unit *u) {
     717           0 :         assert(u);
     718             : 
     719           0 :         return state_translation_table[TIMER(u)->state];
     720             : }
     721             : 
     722           0 : _pure_ static const char *timer_sub_state_to_string(Unit *u) {
     723           0 :         assert(u);
     724             : 
     725           0 :         return timer_state_to_string(TIMER(u)->state);
     726             : }
     727             : 
     728           0 : static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
     729           0 :         Timer *t = TIMER(userdata);
     730             : 
     731           0 :         assert(t);
     732             : 
     733           0 :         if (t->state != TIMER_WAITING)
     734           0 :                 return 0;
     735             : 
     736           0 :         log_unit_debug(UNIT(t), "Timer elapsed.");
     737           0 :         timer_enter_running(t);
     738           0 :         return 0;
     739             : }
     740             : 
     741           0 : static void timer_trigger_notify(Unit *u, Unit *other) {
     742           0 :         Timer *t = TIMER(u);
     743             :         TimerValue *v;
     744             : 
     745           0 :         assert(u);
     746           0 :         assert(other);
     747             : 
     748           0 :         if (other->load_state != UNIT_LOADED)
     749           0 :                 return;
     750             : 
     751             :         /* Reenable all timers that depend on unit state */
     752           0 :         LIST_FOREACH(value, v, t->values)
     753           0 :                 if (IN_SET(v->base, TIMER_UNIT_ACTIVE, TIMER_UNIT_INACTIVE))
     754           0 :                         v->disabled = false;
     755             : 
     756           0 :         switch (t->state) {
     757             : 
     758           0 :         case TIMER_WAITING:
     759             :         case TIMER_ELAPSED:
     760             : 
     761             :                 /* Recalculate sleep time */
     762           0 :                 timer_enter_waiting(t, false);
     763           0 :                 break;
     764             : 
     765           0 :         case TIMER_RUNNING:
     766             : 
     767           0 :                 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
     768           0 :                         log_unit_debug(UNIT(t), "Got notified about unit deactivation.");
     769           0 :                         timer_enter_waiting(t, false);
     770             :                 }
     771           0 :                 break;
     772             : 
     773           0 :         case TIMER_DEAD:
     774             :         case TIMER_FAILED:
     775           0 :                 break;
     776             : 
     777           0 :         default:
     778           0 :                 assert_not_reached("Unknown timer state");
     779             :         }
     780             : }
     781             : 
     782           0 : static void timer_reset_failed(Unit *u) {
     783           0 :         Timer *t = TIMER(u);
     784             : 
     785           0 :         assert(t);
     786             : 
     787           0 :         if (t->state == TIMER_FAILED)
     788           0 :                 timer_set_state(t, TIMER_DEAD);
     789             : 
     790           0 :         t->result = TIMER_SUCCESS;
     791           0 : }
     792             : 
     793           0 : static void timer_time_change(Unit *u) {
     794           0 :         Timer *t = TIMER(u);
     795             :         usec_t ts;
     796             : 
     797           0 :         assert(u);
     798             : 
     799           0 :         if (t->state != TIMER_WAITING)
     800           0 :                 return;
     801             : 
     802             :         /* If we appear to have triggered in the future, the system clock must
     803             :          * have been set backwards.  So let's rewind our own clock and allow
     804             :          * the future trigger(s) to happen again :).  Exactly the same as when
     805             :          * you start a timer unit with Persistent=yes. */
     806           0 :         ts = now(CLOCK_REALTIME);
     807           0 :         if (t->last_trigger.realtime > ts)
     808           0 :                 t->last_trigger.realtime = ts;
     809             : 
     810           0 :         if (t->on_clock_change) {
     811           0 :                 log_unit_debug(u, "Time change, triggering activation.");
     812           0 :                 timer_enter_running(t);
     813             :         } else {
     814           0 :                 log_unit_debug(u, "Time change, recalculating next elapse.");
     815           0 :                 timer_enter_waiting(t, true);
     816             :         }
     817             : }
     818             : 
     819           0 : static void timer_timezone_change(Unit *u) {
     820           0 :         Timer *t = TIMER(u);
     821             : 
     822           0 :         assert(u);
     823             : 
     824           0 :         if (t->state != TIMER_WAITING)
     825           0 :                 return;
     826             : 
     827           0 :         if (t->on_timezone_change) {
     828           0 :                 log_unit_debug(u, "Timezone change, triggering activation.");
     829           0 :                 timer_enter_running(t);
     830             :         } else {
     831           0 :                 log_unit_debug(u, "Timezone change, recalculating next elapse.");
     832           0 :                 timer_enter_waiting(t, false);
     833             :         }
     834             : }
     835             : 
     836           0 : static int timer_clean(Unit *u, ExecCleanMask mask) {
     837           0 :         Timer *t = TIMER(u);
     838             :         int r;
     839             : 
     840           0 :         assert(t);
     841           0 :         assert(mask != 0);
     842             : 
     843           0 :         if (t->state != TIMER_DEAD)
     844           0 :                 return -EBUSY;
     845             : 
     846           0 :         if (!IN_SET(mask, EXEC_CLEAN_STATE))
     847           0 :                 return -EUNATCH;
     848             : 
     849           0 :         r = timer_setup_persistent(t);
     850           0 :         if (r < 0)
     851           0 :                 return r;
     852             : 
     853           0 :         if (!t->stamp_path)
     854           0 :                 return -EUNATCH;
     855             : 
     856           0 :         if (unlink(t->stamp_path) && errno != ENOENT)
     857           0 :                 return log_unit_error_errno(u, errno, "Failed to clean stamp file of timer: %m");
     858             : 
     859           0 :         return 0;
     860             : }
     861             : 
     862           0 : static int timer_can_clean(Unit *u, ExecCleanMask *ret) {
     863           0 :         Timer *t = TIMER(u);
     864             : 
     865           0 :         assert(t);
     866             : 
     867           0 :         *ret = t->persistent ? EXEC_CLEAN_STATE : 0;
     868           0 :         return 0;
     869             : }
     870             : 
     871             : static const char* const timer_base_table[_TIMER_BASE_MAX] = {
     872             :         [TIMER_ACTIVE] = "OnActiveSec",
     873             :         [TIMER_BOOT] = "OnBootSec",
     874             :         [TIMER_STARTUP] = "OnStartupSec",
     875             :         [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
     876             :         [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
     877             :         [TIMER_CALENDAR] = "OnCalendar"
     878             : };
     879             : 
     880          16 : DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
     881             : 
     882             : static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
     883             :         [TIMER_SUCCESS] = "success",
     884             :         [TIMER_FAILURE_RESOURCES] = "resources",
     885             :         [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
     886             : };
     887             : 
     888          10 : DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
     889             : 
     890             : const UnitVTable timer_vtable = {
     891             :         .object_size = sizeof(Timer),
     892             : 
     893             :         .sections =
     894             :                 "Unit\0"
     895             :                 "Timer\0"
     896             :                 "Install\0",
     897             :         .private_section = "Timer",
     898             : 
     899             :         .init = timer_init,
     900             :         .done = timer_done,
     901             :         .load = timer_load,
     902             : 
     903             :         .coldplug = timer_coldplug,
     904             : 
     905             :         .dump = timer_dump,
     906             : 
     907             :         .start = timer_start,
     908             :         .stop = timer_stop,
     909             : 
     910             :         .clean = timer_clean,
     911             :         .can_clean = timer_can_clean,
     912             : 
     913             :         .serialize = timer_serialize,
     914             :         .deserialize_item = timer_deserialize_item,
     915             : 
     916             :         .active_state = timer_active_state,
     917             :         .sub_state_to_string = timer_sub_state_to_string,
     918             : 
     919             :         .trigger_notify = timer_trigger_notify,
     920             : 
     921             :         .reset_failed = timer_reset_failed,
     922             :         .time_change = timer_time_change,
     923             :         .timezone_change = timer_timezone_change,
     924             : 
     925             :         .bus_vtable = bus_timer_vtable,
     926             :         .bus_set_property = bus_timer_set_property,
     927             : 
     928             :         .can_transient = true,
     929             : };

Generated by: LCOV version 1.14