94
94
struct sockaddr sa;
95
95
struct sockaddr_un un;
97
struct epoll_event ev;
97
.sa.sa_family = AF_UNIX,
99
struct epoll_event ev = {
101
.data.ptr = &m->notify_watch,
102
105
m->notify_watch.type = WATCH_NOTIFY;
103
106
m->notify_watch.fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
110
sa.sa.sa_family = AF_UNIX;
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());
117
117
sa.un.sun_path[0] = 0;
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));
120
122
log_error("bind() failed: %m");
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));
125
128
log_error("SO_PASSCRED failed: %m");
131
ev.data.ptr = &m->notify_watch;
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);
134
134
log_error("Failed to add notification socket fd to epoll: %m");
148
148
static int manager_jobs_in_progress_mod_timer(Manager *m) {
149
struct itimerspec its;
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,
154
if (m->jobs_in_progress_watch.type != WATCH_JOBS_IN_PROGRESS)
156
157
if (timerfd_settime(m->jobs_in_progress_watch.fd, 0, &its, NULL) < 0)
162
163
static int manager_watch_jobs_in_progress(Manager *m) {
163
struct epoll_event ev;
164
struct epoll_event ev = {
166
.data.ptr = &m->jobs_in_progress_watch,
168
170
if (m->jobs_in_progress_watch.type != WATCH_INVALID)
187
ev.data.ptr = &m->jobs_in_progress_watch;
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");
223
221
assert(pos <= width+1); /* 0 or width+1 mean that the center light is behind the corner */
227
memset(p, ' ', pos-2);
230
memcpy(p, ANSI_RED_ON, strlen(ANSI_RED_ON));
231
p += strlen(ANSI_RED_ON);
225
p = mempset(p, ' ', pos-2);
226
p = stpcpy(p, ANSI_RED_ON);
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);
241
memcpy(p, ANSI_HIGHLIGHT_OFF, strlen(ANSI_HIGHLIGHT_OFF));
242
p += strlen(ANSI_HIGHLIGHT_OFF);
235
p = stpcpy(p, ANSI_HIGHLIGHT_OFF);
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);
249
memset(p, ' ', width-1-pos);
252
memcpy(p, ANSI_HIGHLIGHT_OFF, strlen(ANSI_HIGHLIGHT_OFF));
253
p += strlen(ANSI_HIGHLIGHT_OFF);
241
p = mempset(p, ' ', width-1-pos);
242
p = stpcpy(p, ANSI_HIGHLIGHT_OFF);
258
246
static void manager_print_jobs_in_progress(Manager *m) {
292
280
static int manager_setup_time_change(Manager *m) {
293
struct epoll_event ev;
294
struct itimerspec its;
281
struct epoll_event ev = {
283
.data.ptr = &m->time_change_watch,
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,
291
assert_cc(sizeof(time_t) == sizeof(TIME_T_MAX));
297
293
assert(m->time_change_watch.type == WATCH_INVALID);
299
295
/* Uses TFD_TIMER_CANCEL_ON_SET to get notifications whenever
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;
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);
325
ev.data.ptr = &m->time_change_watch;
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");
364
349
static int manager_setup_signals(Manager *m) {
366
struct epoll_event ev;
351
struct epoll_event ev = {
353
.data.ptr = &m->signal_watch,
355
struct sigaction sa = {
356
.sa_handler = SIG_DFL,
357
.sa_flags = SA_NOCLDSTOP|SA_RESTART,
371
362
/* We are not interested in SIGSTOP and friends. */
373
sa.sa_handler = SIG_DFL;
374
sa.sa_flags = SA_NOCLDSTOP|SA_RESTART;
375
363
assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
377
365
assert_se(sigemptyset(&mask) == 0);
413
401
if (m->signal_watch.fd < 0)
418
ev.data.ptr = &m->signal_watch;
420
404
if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->signal_watch.fd, &ev) < 0)
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);
465
451
m->running_as = running_as;
466
452
m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
1189
1175
char buf[4096];
1190
struct msghdr msghdr;
1192
struct ucred *ucred;
1176
struct iovec iovec = {
1178
.iov_len = sizeof(buf)-1,
1194
1182
struct cmsghdr cmsghdr;
1195
1183
uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
1186
struct msghdr msghdr = {
1189
.msg_control = &control,
1190
.msg_controllen = sizeof(control),
1192
struct ucred *ucred;
1201
iovec.iov_base = buf;
1202
iovec.iov_len = sizeof(buf)-1;
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;
1211
1196
n = recvmsg(m->notify_watch.fd, &msghdr, MSG_DONTWAIT);
1216
1201
if (errno == EAGAIN || errno == EINTR)
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;
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));
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);
1909
1891
log_error("socket() failed: %m");
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) {
2053
2034
dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp);
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;
2061
fprintf(f, "env=%s\n", *e);
2043
fprintf(f, "env=%s\n", *e);
2064
2047
fputc('\n', f);
2074
2057
fputs(u->id, f);
2075
2058
fputc('\n', f);
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 --;
2265
r = manager_serialize(m, f, fds, true);
2248
r = manager_serialize(m, f, fds, false);
2267
2250
m->n_reloading --;
2373
2362
if (m->n_running_jobs == 0)
2374
2363
manager_unwatch_jobs_in_progress(m);
2376
if (hashmap_size(m->jobs) > 0)
2365
if (hashmap_size(m->jobs) > 0) {
2366
manager_jobs_in_progress_mod_timer(m);
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),
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),
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),
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));
2454
2445
static int create_generator_dir(Manager *m, char **generator, const char *name) {
2545
2535
argv[3] = m->generator_unit_path_late;
2546
2536
argv[4] = NULL;
2549
execute_directory(generator_path, d, (char**) argv);
2538
RUN_WITH_UMASK(0022) {
2539
execute_directory(generator_path, d, (char**) argv);
2552
2542
trim_generator_dir(m, &m->generator_unit_path);
2553
2543
trim_generator_dir(m, &m->generator_unit_path_early);