~ubuntu-branches/ubuntu/trusty/systemd/trusty

« back to all changes in this revision

Viewing changes to src/core/manager.c

Tags: upstream-202
ImportĀ upstreamĀ versionĀ 202

Show diffs side-by-side

added added

removed removed

Lines of Context:
93
93
        union {
94
94
                struct sockaddr sa;
95
95
                struct sockaddr_un un;
96
 
        } sa;
97
 
        struct epoll_event ev;
98
 
        int one = 1;
99
 
 
100
 
        assert(m);
 
96
        } sa = {
 
97
                .sa.sa_family = AF_UNIX,
 
98
        };
 
99
        struct epoll_event ev = {
 
100
                .events = EPOLLIN,
 
101
                .data.ptr = &m->notify_watch,
 
102
        };
 
103
        int one = 1, r;
101
104
 
102
105
        m->notify_watch.type = WATCH_NOTIFY;
103
106
        m->notify_watch.fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
106
109
                return -errno;
107
110
        }
108
111
 
109
 
        zero(sa);
110
 
        sa.sa.sa_family = AF_UNIX;
111
 
 
112
112
        if (getpid() != 1 || detect_container(NULL) > 0)
113
113
                snprintf(sa.un.sun_path, sizeof(sa.un.sun_path), NOTIFY_SOCKET "/%llu", random_ull());
114
114
        else
116
116
 
117
117
        sa.un.sun_path[0] = 0;
118
118
 
119
 
        if (bind(m->notify_watch.fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
 
119
        r = bind(m->notify_watch.fd, &sa.sa,
 
120
                 offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1));
 
121
        if (r < 0) {
120
122
                log_error("bind() failed: %m");
121
123
                return -errno;
122
124
        }
123
125
 
124
 
        if (setsockopt(m->notify_watch.fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) {
 
126
        r = setsockopt(m->notify_watch.fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
 
127
        if (r < 0) {
125
128
                log_error("SO_PASSCRED failed: %m");
126
129
                return -errno;
127
130
        }
128
131
 
129
 
        zero(ev);
130
 
        ev.events = EPOLLIN;
131
 
        ev.data.ptr = &m->notify_watch;
132
 
 
133
 
        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0) {
 
132
        r = epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev);
 
133
        if (r < 0) {
134
134
                log_error("Failed to add notification socket fd to epoll: %m");
135
135
                return -errno;
136
136
        }
146
146
}
147
147
 
148
148
static int manager_jobs_in_progress_mod_timer(Manager *m) {
149
 
        struct itimerspec its;
150
 
 
151
 
        zero(its);
152
 
 
153
 
        its.it_value.tv_sec = JOBS_IN_PROGRESS_WAIT_SEC;
154
 
        its.it_interval.tv_sec = JOBS_IN_PROGRESS_PERIOD_SEC;
 
149
        struct itimerspec its = {
 
150
                .it_value.tv_sec = JOBS_IN_PROGRESS_WAIT_SEC,
 
151
                .it_interval.tv_sec = JOBS_IN_PROGRESS_PERIOD_SEC,
 
152
        };
 
153
 
 
154
        if (m->jobs_in_progress_watch.type != WATCH_JOBS_IN_PROGRESS)
 
155
                return 0;
155
156
 
156
157
        if (timerfd_settime(m->jobs_in_progress_watch.fd, 0, &its, NULL) < 0)
157
158
                return -errno;
160
161
}
161
162
 
162
163
static int manager_watch_jobs_in_progress(Manager *m) {
163
 
        struct epoll_event ev;
 
164
        struct epoll_event ev = {
 
165
                .events = EPOLLIN,
 
166
                .data.ptr = &m->jobs_in_progress_watch,
 
167
        };
164
168
        int r;
165
169
 
166
 
        assert(m);
167
 
 
168
170
        if (m->jobs_in_progress_watch.type != WATCH_INVALID)
169
171
                return 0;
170
172
 
182
184
                goto err;
183
185
        }
184
186
 
185
 
        zero(ev);
186
 
        ev.events = EPOLLIN;
187
 
        ev.data.ptr = &m->jobs_in_progress_watch;
188
 
 
189
187
        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->jobs_in_progress_watch.fd, &ev) < 0) {
190
188
                log_error("Failed to add jobs progress timer fd to epoll: %m");
191
189
                r = -errno;
223
221
        assert(pos <= width+1); /* 0 or width+1 mean that the center light is behind the corner */
224
222
 
225
223
        if (pos > 1) {
226
 
                if (pos > 2) {
227
 
                        memset(p, ' ', pos-2);
228
 
                        p += pos-2;
229
 
                }
230
 
                memcpy(p, ANSI_RED_ON, strlen(ANSI_RED_ON));
231
 
                p += strlen(ANSI_RED_ON);
 
224
                if (pos > 2)
 
225
                        p = mempset(p, ' ', pos-2);
 
226
                p = stpcpy(p, ANSI_RED_ON);
232
227
                *p++ = '*';
233
228
        }
234
229
 
235
230
        if (pos > 0 && pos <= width) {
236
 
                memcpy(p, ANSI_HIGHLIGHT_RED_ON, strlen(ANSI_HIGHLIGHT_RED_ON));
237
 
                p += strlen(ANSI_HIGHLIGHT_RED_ON);
 
231
                p = stpcpy(p, ANSI_HIGHLIGHT_RED_ON);
238
232
                *p++ = '*';
239
233
        }
240
234
 
241
 
        memcpy(p, ANSI_HIGHLIGHT_OFF, strlen(ANSI_HIGHLIGHT_OFF));
242
 
        p += strlen(ANSI_HIGHLIGHT_OFF);
 
235
        p = stpcpy(p, ANSI_HIGHLIGHT_OFF);
243
236
 
244
237
        if (pos < width) {
245
 
                memcpy(p, ANSI_RED_ON, strlen(ANSI_RED_ON));
246
 
                p += strlen(ANSI_RED_ON);
 
238
                p = stpcpy(p, ANSI_RED_ON);
247
239
                *p++ = '*';
248
 
                if (pos < width-1) {
249
 
                        memset(p, ' ', width-1-pos);
250
 
                        p += width-1-pos;
251
 
                }
252
 
                memcpy(p, ANSI_HIGHLIGHT_OFF, strlen(ANSI_HIGHLIGHT_OFF));
253
 
                p += strlen(ANSI_HIGHLIGHT_OFF);
 
240
                if (pos < width-1)
 
241
                        p = mempset(p, ' ', width-1-pos);
 
242
                p = stpcpy(p, ANSI_HIGHLIGHT_OFF);
254
243
        }
255
 
        *p = 0;
256
244
}
257
245
 
258
246
static void manager_print_jobs_in_progress(Manager *m) {
290
278
}
291
279
 
292
280
static int manager_setup_time_change(Manager *m) {
293
 
        struct epoll_event ev;
294
 
        struct itimerspec its;
295
 
 
296
 
        assert(m);
 
281
        struct epoll_event ev = {
 
282
                .events = EPOLLIN,
 
283
                .data.ptr = &m->time_change_watch,
 
284
        };
 
285
 
 
286
        /* We only care for the cancellation event, hence we set the
 
287
         * timeout to the latest possible value. */
 
288
        struct itimerspec its = {
 
289
                .it_value.tv_sec = TIME_T_MAX,
 
290
        };
 
291
        assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
 
292
 
297
293
        assert(m->time_change_watch.type == WATCH_INVALID);
298
294
 
299
295
        /* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever
306
302
                return -errno;
307
303
        }
308
304
 
309
 
        zero(its);
310
 
 
311
 
        /* We only care for the cancellation event, hence we set the
312
 
         * timeout to the latest possible value. */
313
 
        assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
314
 
        its.it_value.tv_sec = TIME_T_MAX;
315
 
 
316
305
        if (timerfd_settime(m->time_change_watch.fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &its, NULL) < 0) {
317
306
                log_debug("Failed to set up TFD_TIMER_CANCEL_ON_SET, ignoring: %m");
318
307
                close_nointr_nofail(m->time_change_watch.fd);
320
309
                return 0;
321
310
        }
322
311
 
323
 
        zero(ev);
324
 
        ev.events = EPOLLIN;
325
 
        ev.data.ptr = &m->time_change_watch;
326
 
 
327
312
        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->time_change_watch.fd, &ev) < 0) {
328
313
                log_error("Failed to add timer change fd to epoll: %m");
329
314
                return -errno;
363
348
 
364
349
static int manager_setup_signals(Manager *m) {
365
350
        sigset_t mask;
366
 
        struct epoll_event ev;
367
 
        struct sigaction sa;
 
351
        struct epoll_event ev = {
 
352
                .events = EPOLLIN,
 
353
                .data.ptr = &m->signal_watch,
 
354
        };
 
355
        struct sigaction sa = {
 
356
                .sa_handler = SIG_DFL,
 
357
                .sa_flags = SA_NOCLDSTOP|SA_RESTART,
 
358
        };
368
359
 
369
360
        assert(m);
370
361
 
371
362
        /* We are not interested in SIGSTOP and friends. */
372
 
        zero(sa);
373
 
        sa.sa_handler = SIG_DFL;
374
 
        sa.sa_flags = SA_NOCLDSTOP|SA_RESTART;
375
363
        assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
376
364
 
377
365
        assert_se(sigemptyset(&mask) == 0);
413
401
        if (m->signal_watch.fd < 0)
414
402
                return -errno;
415
403
 
416
 
        zero(ev);
417
 
        ev.events = EPOLLIN;
418
 
        ev.data.ptr = &m->signal_watch;
419
 
 
420
404
        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->signal_watch.fd, &ev) < 0)
421
405
                return -errno;
422
406
 
457
441
                return -ENOMEM;
458
442
 
459
443
        dual_timestamp_get(&m->userspace_timestamp);
460
 
        dual_timestamp_from_monotonic(&m->kernel_timestamp, 0);
 
444
        if (detect_container(NULL) <= 0) {
 
445
                dual_timestamp_from_monotonic(&m->kernel_timestamp, 0);
461
446
#ifdef ENABLE_EFI
462
 
        efi_get_boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp);
 
447
                efi_get_boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp);
463
448
#endif
 
449
        }
464
450
 
465
451
        m->running_as = running_as;
466
452
        m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
782
768
 
783
769
static void manager_build_unit_path_cache(Manager *m) {
784
770
        char **i;
785
 
        DIR _cleanup_free_ *d = NULL;
 
771
        _cleanup_free_ DIR *d = NULL;
786
772
        int r;
787
773
 
788
774
        assert(m);
1187
1173
 
1188
1174
        for (;;) {
1189
1175
                char buf[4096];
1190
 
                struct msghdr msghdr;
1191
 
                struct iovec iovec;
1192
 
                struct ucred *ucred;
 
1176
                struct iovec iovec = {
 
1177
                        .iov_base = buf,
 
1178
                        .iov_len = sizeof(buf)-1,
 
1179
                };
 
1180
 
1193
1181
                union {
1194
1182
                        struct cmsghdr cmsghdr;
1195
1183
                        uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
1196
 
                } control;
 
1184
                } control = {};
 
1185
 
 
1186
                struct msghdr msghdr = {
 
1187
                        .msg_iov = &iovec,
 
1188
                        .msg_iovlen = 1,
 
1189
                        .msg_control = &control,
 
1190
                        .msg_controllen = sizeof(control),
 
1191
                };
 
1192
                struct ucred *ucred;
1197
1193
                Unit *u;
1198
 
                char **tags;
1199
 
 
1200
 
                zero(iovec);
1201
 
                iovec.iov_base = buf;
1202
 
                iovec.iov_len = sizeof(buf)-1;
1203
 
 
1204
 
                zero(control);
1205
 
                zero(msghdr);
1206
 
                msghdr.msg_iov = &iovec;
1207
 
                msghdr.msg_iovlen = 1;
1208
 
                msghdr.msg_control = &control;
1209
 
                msghdr.msg_controllen = sizeof(control);
 
1194
                _cleanup_strv_free_ char **tags = NULL;
1210
1195
 
1211
1196
                n = recvmsg(m->notify_watch.fd, &msghdr, MSG_DONTWAIT);
1212
1197
                if (n <= 0) {
1213
 
                        if (n >= 0)
 
1198
                        if (n == 0)
1214
1199
                                return -EIO;
1215
1200
 
1216
1201
                        if (errno == EAGAIN || errno == EINTR)
1248
1233
 
1249
1234
                if (UNIT_VTABLE(u)->notify_message)
1250
1235
                        UNIT_VTABLE(u)->notify_message(u, ucred->pid, tags);
1251
 
 
1252
 
                strv_free(tags);
1253
1236
        }
1254
1237
 
1255
1238
        return 0;
1259
1242
        assert(m);
1260
1243
 
1261
1244
        for (;;) {
1262
 
                siginfo_t si;
 
1245
                siginfo_t si = {};
1263
1246
                Unit *u;
1264
1247
                int r;
1265
1248
 
1266
 
                zero(si);
1267
 
 
1268
1249
                /* First we call waitd() for a PID and do not reap the
1269
1250
                 * zombie. That way we can still access /proc/$PID for
1270
1251
                 * it while it is a zombie. */
1283
1264
                        break;
1284
1265
 
1285
1266
                if (si.si_code == CLD_EXITED || si.si_code == CLD_KILLED || si.si_code == CLD_DUMPED) {
1286
 
                        char _cleanup_free_ *name = NULL;
 
1267
                        _cleanup_free_ char *name = NULL;
1287
1268
 
1288
1269
                        get_process_comm(si.si_pid, &name);
1289
1270
                        log_debug("Got SIGCHLD for process %lu (%s)", (unsigned long) si.si_pid, strna(name));
1905
1886
 
1906
1887
        /* We set SOCK_NONBLOCK here so that we rather drop the
1907
1888
         * message then wait for plymouth */
1908
 
        if ((fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
 
1889
        fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
 
1890
        if (fd < 0) {
1909
1891
                log_error("socket() failed: %m");
1910
1892
                return;
1911
1893
        }
1988
1970
 
1989
1971
int manager_open_serialization(Manager *m, FILE **_f) {
1990
1972
        char *path = NULL;
1991
 
        mode_t saved_umask;
1992
1973
        int fd;
1993
1974
        FILE *f;
1994
1975
 
2002
1983
        if (!path)
2003
1984
                return -ENOMEM;
2004
1985
 
2005
 
        saved_umask = umask(0077);
2006
 
        fd = mkostemp(path, O_RDWR|O_CLOEXEC);
2007
 
        umask(saved_umask);
 
1986
        RUN_WITH_UMASK(0077) {
 
1987
                fd = mkostemp(path, O_RDWR|O_CLOEXEC);
 
1988
        }
2008
1989
 
2009
1990
        if (fd < 0) {
2010
1991
                free(path);
2025
2006
        return 0;
2026
2007
}
2027
2008
 
2028
 
int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool serialize_jobs) {
 
2009
int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) {
2029
2010
        Iterator i;
2030
2011
        Unit *u;
2031
2012
        const char *t;
2053
2034
                dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp);
2054
2035
        }
2055
2036
 
2056
 
        STRV_FOREACH(e, m->environment) {
2057
 
                _cleanup_free_ char *ce;
 
2037
        if (!switching_root) {
 
2038
                STRV_FOREACH(e, m->environment) {
 
2039
                        _cleanup_free_ char *ce;
2058
2040
 
2059
 
                ce = cescape(*e);
2060
 
                if (ce)
2061
 
                        fprintf(f, "env=%s\n", *e);
 
2041
                        ce = cescape(*e);
 
2042
                        if (ce)
 
2043
                                fprintf(f, "env=%s\n", *e);
 
2044
                }
2062
2045
        }
2063
2046
 
2064
2047
        fputc('\n', f);
2074
2057
                fputs(u->id, f);
2075
2058
                fputc('\n', f);
2076
2059
 
2077
 
                if ((r = unit_serialize(u, f, fds, serialize_jobs)) < 0) {
 
2060
                if ((r = unit_serialize(u, f, fds, !switching_root)) < 0) {
2078
2061
                        m->n_reloading --;
2079
2062
                        return r;
2080
2063
                }
2262
2245
                goto finish;
2263
2246
        }
2264
2247
 
2265
 
        r = manager_serialize(m, f, fds, true);
 
2248
        r = manager_serialize(m, f, fds, false);
2266
2249
        if (r < 0) {
2267
2250
                m->n_reloading --;
2268
2251
                goto finish;
2340
2323
        return false;
2341
2324
}
2342
2325
 
 
2326
bool manager_is_reloading_or_reexecuting(Manager *m) {
 
2327
        assert(m);
 
2328
 
 
2329
        return m->n_reloading != 0;
 
2330
}
 
2331
 
2343
2332
void manager_reset_failed(Manager *m) {
2344
2333
        Unit *u;
2345
2334
        Iterator i;
2373
2362
        if (m->n_running_jobs == 0)
2374
2363
                manager_unwatch_jobs_in_progress(m);
2375
2364
 
2376
 
        if (hashmap_size(m->jobs) > 0)
 
2365
        if (hashmap_size(m->jobs) > 0) {
 
2366
                manager_jobs_in_progress_mod_timer(m);
2377
2367
                return;
 
2368
        }
2378
2369
 
2379
2370
        /* Notify Type=idle units that we are done now */
2380
2371
        close_pipe(m->idle_pipe);
2411
2402
                                           "INITRD_USEC=%llu", (unsigned long long) initrd_usec,
2412
2403
                                           "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
2413
2404
                                           "MESSAGE=Startup finished in %s (kernel) + %s (initrd) + %s (userspace) = %s.",
2414
 
                                           format_timespan(kernel, sizeof(kernel), kernel_usec),
2415
 
                                           format_timespan(initrd, sizeof(initrd), initrd_usec),
2416
 
                                           format_timespan(userspace, sizeof(userspace), userspace_usec),
2417
 
                                           format_timespan(sum, sizeof(sum), total_usec),
 
2405
                                           format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC),
 
2406
                                           format_timespan(initrd, sizeof(initrd), initrd_usec, USEC_PER_MSEC),
 
2407
                                           format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC),
 
2408
                                           format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC),
2418
2409
                                           NULL);
2419
2410
                } else {
2420
2411
                        kernel_usec = m->userspace_timestamp.monotonic - m->kernel_timestamp.monotonic;
2426
2417
                                           "KERNEL_USEC=%llu", (unsigned long long) kernel_usec,
2427
2418
                                           "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
2428
2419
                                           "MESSAGE=Startup finished in %s (kernel) + %s (userspace) = %s.",
2429
 
                                           format_timespan(kernel, sizeof(kernel), kernel_usec),
2430
 
                                           format_timespan(userspace, sizeof(userspace), userspace_usec),
2431
 
                                           format_timespan(sum, sizeof(sum), total_usec),
 
2420
                                           format_timespan(kernel, sizeof(kernel), kernel_usec, USEC_PER_MSEC),
 
2421
                                           format_timespan(userspace, sizeof(userspace), userspace_usec, USEC_PER_MSEC),
 
2422
                                           format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC),
2432
2423
                                           NULL);
2433
2424
                }
2434
2425
        } else {
2440
2431
                                   MESSAGE_ID(SD_MESSAGE_STARTUP_FINISHED),
2441
2432
                                   "USERSPACE_USEC=%llu", (unsigned long long) userspace_usec,
2442
2433
                                   "MESSAGE=Startup finished in %s.",
2443
 
                                   format_timespan(sum, sizeof(sum), total_usec),
 
2434
                                   format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC),
2444
2435
                                   NULL);
2445
2436
        }
2446
2437
 
2448
2439
 
2449
2440
        sd_notifyf(false,
2450
2441
                   "READY=1\nSTATUS=Startup finished in %s.",
2451
 
                   format_timespan(sum, sizeof(sum), total_usec));
 
2442
                   format_timespan(sum, sizeof(sum), total_usec, USEC_PER_MSEC));
2452
2443
}
2453
2444
 
2454
2445
static int create_generator_dir(Manager *m, char **generator, const char *name) {
2511
2502
        DIR *d = NULL;
2512
2503
        const char *generator_path;
2513
2504
        const char *argv[5];
2514
 
        mode_t u;
2515
2505
        int r;
2516
2506
 
2517
2507
        assert(m);
2545
2535
        argv[3] = m->generator_unit_path_late;
2546
2536
        argv[4] = NULL;
2547
2537
 
2548
 
        u = umask(0022);
2549
 
        execute_directory(generator_path, d, (char**) argv);
2550
 
        umask(u);
 
2538
        RUN_WITH_UMASK(0022) {
 
2539
                execute_directory(generator_path, d, (char**) argv);
 
2540
        }
2551
2541
 
2552
2542
        trim_generator_dir(m, &m->generator_unit_path);
2553
2543
        trim_generator_dir(m, &m->generator_unit_path_early);