~ubuntu-branches/debian/jessie/systemd/jessie

« back to all changes in this revision

Viewing changes to src/timer.c

  • Committer: Package Import Robot
  • Author(s): Tollef Fog Heen, Tollef Fog Heen, Michael Biebl
  • Date: 2012-04-03 19:59:17 UTC
  • mfrom: (1.1.10) (6.1.3 experimental)
  • Revision ID: package-import@ubuntu.com-20120403195917-l532urrbg4pkreas
Tags: 44-1
[ Tollef Fog Heen ]
* New upstream version.
  - Backport 3492207: journal: PAGE_SIZE is not known on ppc and other
    archs
  - Backport 5a2a2a1: journal: react with immediate rotation to a couple
    of more errors
  - Backport 693ce21: util: never follow symlinks in rm_rf_children()
    Fixes CVE-2012-1174, closes: #664364
* Drop output message from init-functions hook, it's pointless.
* Only rmdir /lib/init/rw if it exists.
* Explicitly order debian-fixup before sysinit.target to prevent a
  possible race condition with the creation of sockets.  Thanks to
  Michael Biebl for debugging this.
* Always restart the initctl socket on upgrades, to mask sysvinit
  removing it.

[ Michael Biebl ]
* Remove workaround for non-interactive sessions from pam config again.
* Create compat /dev/initctl symlink in case we are upgrading from a system
  running a newer version of sysvinit (using /run/initctl) and sysvinit is
  replaced with systemd-sysv during the upgrade. Closes: #663219
* Install new man pages.
* Build-Depend on valac (>= 0.12) instead of valac-0.12. Closes: #663323

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
        Timer *t = TIMER(u);
41
41
 
42
42
        assert(u);
43
 
        assert(u->meta.load_state == UNIT_STUB);
 
43
        assert(u->load_state == UNIT_STUB);
44
44
 
45
45
        t->next_elapse = (usec_t) -1;
46
46
}
57
57
        }
58
58
 
59
59
        unit_unwatch_timer(u, &t->timer_watch);
 
60
 
 
61
        unit_ref_unset(&t->unit);
60
62
}
61
63
 
62
64
static int timer_verify(Timer *t) {
63
65
        assert(t);
64
66
 
65
 
        if (t->meta.load_state != UNIT_LOADED)
 
67
        if (UNIT(t)->load_state != UNIT_LOADED)
66
68
                return 0;
67
69
 
68
70
        if (!t->values) {
69
 
                log_error("%s lacks value setting. Refusing.", t->meta.id);
 
71
                log_error("%s lacks value setting. Refusing.", UNIT(t)->id);
70
72
                return -EINVAL;
71
73
        }
72
74
 
78
80
 
79
81
        assert(t);
80
82
 
81
 
        if (t->meta.manager->running_as == MANAGER_SYSTEM) {
 
83
        if (UNIT(t)->manager->running_as == MANAGER_SYSTEM) {
82
84
                if ((r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_BASIC_TARGET, NULL, true)) < 0)
83
85
                        return r;
84
86
 
94
96
        int r;
95
97
 
96
98
        assert(u);
97
 
        assert(u->meta.load_state == UNIT_STUB);
 
99
        assert(u->load_state == UNIT_STUB);
98
100
 
99
101
        if ((r = unit_load_fragment_and_dropin(u)) < 0)
100
102
                return r;
101
103
 
102
 
        if (u->meta.load_state == UNIT_LOADED) {
103
 
 
104
 
                if (!t->unit)
105
 
                        if ((r = unit_load_related_unit(u, ".service", &t->unit)))
 
104
        if (u->load_state == UNIT_LOADED) {
 
105
 
 
106
                if (!UNIT_DEREF(t->unit)) {
 
107
                        Unit *x;
 
108
 
 
109
                        r = unit_load_related_unit(u, ".service", &x);
 
110
                        if (r < 0)
106
111
                                return r;
107
112
 
108
 
                if ((r = unit_add_dependency(u, UNIT_BEFORE, t->unit, true)) < 0)
 
113
                        unit_ref_set(&t->unit, x);
 
114
                }
 
115
 
 
116
                r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(t->unit), true);
 
117
                if (r < 0)
109
118
                        return r;
110
119
 
111
 
                if (t->meta.default_dependencies)
 
120
                if (UNIT(t)->default_dependencies)
112
121
                        if ((r = timer_add_default_dependencies(t)) < 0)
113
122
                                return r;
114
123
        }
124
133
 
125
134
        fprintf(f,
126
135
                "%sTimer State: %s\n"
 
136
                "%sResult: %s\n"
127
137
                "%sUnit: %s\n",
128
138
                prefix, timer_state_to_string(t->state),
129
 
                prefix, t->unit->meta.id);
 
139
                prefix, timer_result_to_string(t->result),
 
140
                prefix, UNIT_DEREF(t->unit)->id);
130
141
 
131
142
        LIST_FOREACH(value, v, t->values)
132
143
                fprintf(f,
148
159
 
149
160
        if (state != old_state)
150
161
                log_debug("%s changed %s -> %s",
151
 
                          t->meta.id,
 
162
                          UNIT(t)->id,
152
163
                          timer_state_to_string(old_state),
153
164
                          timer_state_to_string(state));
154
165
 
174
185
        return 0;
175
186
}
176
187
 
177
 
static void timer_enter_dead(Timer *t, bool success) {
 
188
static void timer_enter_dead(Timer *t, TimerResult f) {
178
189
        assert(t);
179
190
 
180
 
        if (!success)
181
 
                t->failure = true;
 
191
        if (f != TIMER_SUCCESS)
 
192
                t->result = f;
182
193
 
183
 
        timer_set_state(t, t->failure ? TIMER_FAILED : TIMER_DEAD);
 
194
        timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
184
195
}
185
196
 
186
197
static void timer_enter_waiting(Timer *t, bool initial) {
200
211
 
201
212
                case TIMER_ACTIVE:
202
213
                        if (state_translation_table[t->state] == UNIT_ACTIVE)
203
 
                                base = t->meta.inactive_exit_timestamp.monotonic;
 
214
                                base = UNIT(t)->inactive_exit_timestamp.monotonic;
204
215
                        else
205
216
                                base = n;
206
217
                        break;
211
222
                        break;
212
223
 
213
224
                case TIMER_STARTUP:
214
 
                        base = t->meta.manager->startup_timestamp.monotonic;
 
225
                        base = UNIT(t)->manager->startup_timestamp.monotonic;
215
226
                        break;
216
227
 
217
228
                case TIMER_UNIT_ACTIVE:
218
229
 
219
 
                        if (t->unit->meta.inactive_exit_timestamp.monotonic <= 0)
 
230
                        if (UNIT_DEREF(t->unit)->inactive_exit_timestamp.monotonic <= 0)
220
231
                                continue;
221
232
 
222
 
                        base = t->unit->meta.inactive_exit_timestamp.monotonic;
 
233
                        base = UNIT_DEREF(t->unit)->inactive_exit_timestamp.monotonic;
223
234
                        break;
224
235
 
225
236
                case TIMER_UNIT_INACTIVE:
226
237
 
227
 
                        if (t->unit->meta.inactive_enter_timestamp.monotonic <= 0)
 
238
                        if (UNIT_DEREF(t->unit)->inactive_enter_timestamp.monotonic <= 0)
228
239
                                continue;
229
240
 
230
 
                        base = t->unit->meta.inactive_enter_timestamp.monotonic;
 
241
                        base = UNIT_DEREF(t->unit)->inactive_enter_timestamp.monotonic;
231
242
                        break;
232
243
 
233
244
                default:
263
274
        return;
264
275
 
265
276
fail:
266
 
        log_warning("%s failed to enter waiting state: %s", t->meta.id, strerror(-r));
267
 
        timer_enter_dead(t, false);
 
277
        log_warning("%s failed to enter waiting state: %s", UNIT(t)->id, strerror(-r));
 
278
        timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
268
279
}
269
280
 
270
281
static void timer_enter_running(Timer *t) {
275
286
        dbus_error_init(&error);
276
287
 
277
288
        /* Don't start job if we are supposed to go down */
278
 
        if (t->meta.job && t->meta.job->type == JOB_STOP)
 
289
        if (UNIT(t)->job && UNIT(t)->job->type == JOB_STOP)
279
290
                return;
280
291
 
281
 
        if ((r = manager_add_job(t->meta.manager, JOB_START, t->unit, JOB_REPLACE, true, &error, NULL)) < 0)
 
292
        if ((r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_DEREF(t->unit), JOB_REPLACE, true, &error, NULL)) < 0)
282
293
                goto fail;
283
294
 
284
295
        timer_set_state(t, TIMER_RUNNING);
285
296
        return;
286
297
 
287
298
fail:
288
 
        log_warning("%s failed to queue unit startup job: %s", t->meta.id, bus_error(&error, r));
289
 
        timer_enter_dead(t, false);
 
299
        log_warning("%s failed to queue unit startup job: %s", UNIT(t)->id, bus_error(&error, r));
 
300
        timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
290
301
 
291
302
        dbus_error_free(&error);
292
303
}
297
308
        assert(t);
298
309
        assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
299
310
 
300
 
        if (t->unit->meta.load_state != UNIT_LOADED)
 
311
        if (UNIT_DEREF(t->unit)->load_state != UNIT_LOADED)
301
312
                return -ENOENT;
302
313
 
303
 
        t->failure = false;
 
314
        t->result = TIMER_SUCCESS;
304
315
        timer_enter_waiting(t, true);
305
316
        return 0;
306
317
}
311
322
        assert(t);
312
323
        assert(t->state == TIMER_WAITING || t->state == TIMER_RUNNING || t->state == TIMER_ELAPSED);
313
324
 
314
 
        timer_enter_dead(t, true);
 
325
        timer_enter_dead(t, TIMER_SUCCESS);
315
326
        return 0;
316
327
}
317
328
 
323
334
        assert(fds);
324
335
 
325
336
        unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
 
337
        unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
326
338
 
327
339
        return 0;
328
340
}
342
354
                        log_debug("Failed to parse state value %s", value);
343
355
                else
344
356
                        t->deserialized_state = state;
 
357
        } else if (streq(key, "result")) {
 
358
                TimerResult f;
 
359
 
 
360
                f = timer_result_from_string(value);
 
361
                if (f < 0)
 
362
                        log_debug("Failed to parse result value %s", value);
 
363
                else if (f != TIMER_SUCCESS)
 
364
                        t->result = f;
 
365
 
345
366
        } else
346
367
                log_debug("Unknown serialization key '%s'", key);
347
368
 
369
390
        if (t->state != TIMER_WAITING)
370
391
                return;
371
392
 
372
 
        log_debug("Timer elapsed on %s", u->meta.id);
 
393
        log_debug("Timer elapsed on %s", u->id);
373
394
        timer_enter_running(t);
374
395
}
375
396
 
376
397
void timer_unit_notify(Unit *u, UnitActiveState new_state) {
377
 
        char *n;
378
 
        int r;
379
398
        Iterator i;
 
399
        Unit *k;
380
400
 
381
 
        if (u->meta.type == UNIT_TIMER)
 
401
        if (u->type == UNIT_TIMER)
382
402
                return;
383
403
 
384
 
        SET_FOREACH(n, u->meta.names, i) {
385
 
                char *k;
386
 
                Unit *p;
 
404
        SET_FOREACH(k, u->dependencies[UNIT_TRIGGERED_BY], i) {
387
405
                Timer *t;
388
406
                TimerValue *v;
389
407
 
390
 
                if (!(k = unit_name_change_suffix(n, ".timer"))) {
391
 
                        r = -ENOMEM;
392
 
                        goto fail;
393
 
                }
394
 
 
395
 
                p = manager_get_unit(u->meta.manager, k);
396
 
                free(k);
397
 
 
398
 
                if (!p)
399
 
                        continue;
400
 
 
401
 
                if (p->meta.load_state != UNIT_LOADED)
402
 
                        continue;
403
 
 
404
 
                t = TIMER(p);
405
 
 
406
 
                if (t->unit != u)
407
 
                        continue;
 
408
                if (k->type != UNIT_TIMER)
 
409
                        continue;
 
410
 
 
411
                if (k->load_state != UNIT_LOADED)
 
412
                        continue;
 
413
 
 
414
                t = TIMER(k);
408
415
 
409
416
                /* Reenable all timers that depend on unit state */
410
417
                LIST_FOREACH(value, v, t->values)
424
431
                case TIMER_RUNNING:
425
432
 
426
433
                        if (UNIT_IS_INACTIVE_OR_FAILED(new_state)) {
427
 
                                log_debug("%s got notified about unit deactivation.", t->meta.id);
 
434
                                log_debug("%s got notified about unit deactivation.", UNIT(t)->id);
428
435
                                timer_enter_waiting(t, false);
429
436
                        }
430
437
 
438
445
                        assert_not_reached("Unknown timer state");
439
446
                }
440
447
        }
441
 
 
442
 
        return;
443
 
 
444
 
fail:
445
 
        log_error("Failed find timer unit: %s", strerror(-r));
446
448
}
447
449
 
448
450
static void timer_reset_failed(Unit *u) {
453
455
        if (t->state == TIMER_FAILED)
454
456
                timer_set_state(t, TIMER_DEAD);
455
457
 
456
 
        t->failure = false;
 
458
        t->result = TIMER_SUCCESS;
457
459
}
458
460
 
459
461
static const char* const timer_state_table[_TIMER_STATE_MAX] = {
476
478
 
477
479
DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
478
480
 
 
481
static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
 
482
        [TIMER_SUCCESS] = "success",
 
483
        [TIMER_FAILURE_RESOURCES] = "resources"
 
484
};
 
485
 
 
486
DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
 
487
 
479
488
const UnitVTable timer_vtable = {
480
489
        .suffix = ".timer",
 
490
        .object_size = sizeof(Timer),
481
491
        .sections =
482
492
                "Unit\0"
483
493
                "Timer\0"