1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include <sys/epoll.h>
27 #include <sys/signalfd.h>
31 #include <sys/reboot.h>
32 #include <sys/ioctl.h>
36 #include <sys/types.h>
44 #include <systemd/sd-daemon.h>
47 #include "transaction.h"
54 #include "ratelimit.h"
56 #include "mount-setup.h"
57 #include "unit-name.h"
58 #include "dbus-unit.h"
61 #include "path-lookup.h"
63 #include "bus-errors.h"
64 #include "exit-status.h"
67 #include "cgroup-util.h"
68 #include "path-util.h"
70 /* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
71 #define GC_QUEUE_ENTRIES_MAX 16
73 /* As soon as 5s passed since a unit was added to our GC queue, make sure to run a gc sweep */
74 #define GC_QUEUE_USEC_MAX (10*USEC_PER_SEC)
76 /* Where clients shall send notification messages to */
77 #define NOTIFY_SOCKET_SYSTEM "/run/systemd/notify"
78 #define NOTIFY_SOCKET_USER "@/org/freedesktop/systemd1/notify"
80 static int manager_setup_notify(Manager *m) {
83 struct sockaddr_un un;
85 struct epoll_event ev;
91 m->notify_watch.type = WATCH_NOTIFY;
92 if ((m->notify_watch.fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
93 log_error("Failed to allocate notification socket: %m");
98 sa.sa.sa_family = AF_UNIX;
101 snprintf(sa.un.sun_path, sizeof(sa.un.sun_path), NOTIFY_SOCKET_USER "/%llu", random_ull());
103 unlink(NOTIFY_SOCKET_SYSTEM);
104 strncpy(sa.un.sun_path, NOTIFY_SOCKET_SYSTEM, sizeof(sa.un.sun_path));
107 if (sa.un.sun_path[0] == '@')
108 sa.un.sun_path[0] = 0;
111 r = bind(m->notify_watch.fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1));
115 log_error("bind() failed: %m");
119 if (setsockopt(m->notify_watch.fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0) {
120 log_error("SO_PASSCRED failed: %m");
126 ev.data.ptr = &m->notify_watch;
128 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0)
131 if (sa.un.sun_path[0] == 0)
132 sa.un.sun_path[0] = '@';
134 if (!(m->notify_socket = strdup(sa.un.sun_path)))
137 log_debug("Using notification socket %s", m->notify_socket);
142 static int enable_special_signals(Manager *m) {
147 /* Enable that we get SIGINT on control-alt-del. In containers
148 * this will fail with EPERM, so ignore that. */
149 if (reboot(RB_DISABLE_CAD) < 0 && errno != EPERM)
150 log_warning("Failed to enable ctrl-alt-del handling: %m");
152 fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
154 /* Support systems without virtual console */
156 log_warning("Failed to open /dev/tty0: %m");
158 /* Enable that we get SIGWINCH on kbrequest */
159 if (ioctl(fd, KDSIGACCEPT, SIGWINCH) < 0)
160 log_warning("Failed to enable kbrequest handling: %s", strerror(errno));
162 close_nointr_nofail(fd);
168 static int manager_setup_signals(Manager *m) {
170 struct epoll_event ev;
175 /* We are not interested in SIGSTOP and friends. */
177 sa.sa_handler = SIG_DFL;
178 sa.sa_flags = SA_NOCLDSTOP|SA_RESTART;
179 assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
181 assert_se(sigemptyset(&mask) == 0);
183 sigset_add_many(&mask,
184 SIGCHLD, /* Child died */
185 SIGTERM, /* Reexecute daemon */
186 SIGHUP, /* Reload configuration */
187 SIGUSR1, /* systemd/upstart: reconnect to D-Bus */
188 SIGUSR2, /* systemd: dump status */
189 SIGINT, /* Kernel sends us this on control-alt-del */
190 SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */
191 SIGPWR, /* Some kernel drivers and upsd send us this on power failure */
192 SIGRTMIN+0, /* systemd: start default.target */
193 SIGRTMIN+1, /* systemd: isolate rescue.target */
194 SIGRTMIN+2, /* systemd: isolate emergency.target */
195 SIGRTMIN+3, /* systemd: start halt.target */
196 SIGRTMIN+4, /* systemd: start poweroff.target */
197 SIGRTMIN+5, /* systemd: start reboot.target */
198 SIGRTMIN+6, /* systemd: start kexec.target */
199 SIGRTMIN+13, /* systemd: Immediate halt */
200 SIGRTMIN+14, /* systemd: Immediate poweroff */
201 SIGRTMIN+15, /* systemd: Immediate reboot */
202 SIGRTMIN+16, /* systemd: Immediate kexec */
203 SIGRTMIN+20, /* systemd: enable status messages */
204 SIGRTMIN+21, /* systemd: disable status messages */
205 SIGRTMIN+22, /* systemd: set log level to LOG_DEBUG */
206 SIGRTMIN+23, /* systemd: set log level to LOG_INFO */
207 SIGRTMIN+26, /* systemd: set log target to journal-or-kmsg */
208 SIGRTMIN+27, /* systemd: set log target to console */
209 SIGRTMIN+28, /* systemd: set log target to kmsg */
210 SIGRTMIN+29, /* systemd: set log target to syslog-or-kmsg */
212 assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
214 m->signal_watch.type = WATCH_SIGNAL;
215 if ((m->signal_watch.fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0)
220 ev.data.ptr = &m->signal_watch;
222 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->signal_watch.fd, &ev) < 0)
225 if (m->running_as == MANAGER_SYSTEM)
226 return enable_special_signals(m);
231 static void manager_strip_environment(Manager *m) {
234 /* Remove variables from the inherited set that are part of
235 * the container interface:
236 * http://www.freedesktop.org/wiki/Software/systemd/ContainerInterface */
237 strv_remove_prefix(m->environment, "container=");
238 strv_remove_prefix(m->environment, "container_");
240 /* Remove variables from the inherited set that are part of
241 * the initrd interface:
242 * http://www.freedesktop.org/wiki/Software/systemd/InitrdInterface */
243 strv_remove_prefix(m->environment, "RD_");
246 int manager_new(ManagerRunningAs running_as, Manager **_m) {
251 assert(running_as >= 0);
252 assert(running_as < _MANAGER_RUNNING_AS_MAX);
254 if (!(m = new0(Manager, 1)))
257 dual_timestamp_get(&m->startup_timestamp);
259 m->running_as = running_as;
260 m->name_data_slot = m->conn_data_slot = m->subscribed_data_slot = -1;
261 m->exit_code = _MANAGER_EXIT_CODE_INVALID;
262 m->pin_cgroupfs_fd = -1;
263 m->idle_pipe[0] = m->idle_pipe[1] = -1;
269 m->signal_watch.fd = m->mount_watch.fd = m->udev_watch.fd = m->epoll_fd = m->dev_autofs_fd = m->swap_watch.fd = -1;
270 m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
272 m->environment = strv_copy(environ);
276 manager_strip_environment(m);
278 if (running_as == MANAGER_SYSTEM) {
279 m->default_controllers = strv_new("cpu", NULL);
280 if (!m->default_controllers)
284 if (!(m->units = hashmap_new(string_hash_func, string_compare_func)))
287 if (!(m->jobs = hashmap_new(trivial_hash_func, trivial_compare_func)))
290 if (!(m->watch_pids = hashmap_new(trivial_hash_func, trivial_compare_func)))
293 if (!(m->cgroup_bondings = hashmap_new(string_hash_func, string_compare_func)))
296 if (!(m->watch_bus = hashmap_new(string_hash_func, string_compare_func)))
299 if ((m->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0)
302 if ((r = lookup_paths_init(&m->lookup_paths, m->running_as, true)) < 0)
305 if ((r = manager_setup_signals(m)) < 0)
308 if ((r = manager_setup_cgroup(m)) < 0)
311 if ((r = manager_setup_notify(m)) < 0)
314 /* Try to connect to the busses, if possible. */
315 if ((r = bus_init(m, running_as != MANAGER_SYSTEM)) < 0)
319 if ((m->audit_fd = audit_open()) < 0 &&
320 /* If the kernel lacks netlink or audit support,
321 * don't worry about it. */
322 errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT)
323 log_error("Failed to connect to audit log: %m");
326 m->taint_usr = dir_is_empty("/usr") > 0;
336 static unsigned manager_dispatch_cleanup_queue(Manager *m) {
342 while ((u = m->cleanup_queue)) {
343 assert(u->in_cleanup_queue);
353 GC_OFFSET_IN_PATH, /* This one is on the path we were traveling */
354 GC_OFFSET_UNSURE, /* No clue */
355 GC_OFFSET_GOOD, /* We still need this unit */
356 GC_OFFSET_BAD, /* We don't need this unit anymore */
360 static void unit_gc_sweep(Unit *u, unsigned gc_marker) {
367 if (u->gc_marker == gc_marker + GC_OFFSET_GOOD ||
368 u->gc_marker == gc_marker + GC_OFFSET_BAD ||
369 u->gc_marker == gc_marker + GC_OFFSET_IN_PATH)
372 if (u->in_cleanup_queue)
375 if (unit_check_gc(u))
378 u->gc_marker = gc_marker + GC_OFFSET_IN_PATH;
382 SET_FOREACH(other, u->dependencies[UNIT_REFERENCED_BY], i) {
383 unit_gc_sweep(other, gc_marker);
385 if (other->gc_marker == gc_marker + GC_OFFSET_GOOD)
388 if (other->gc_marker != gc_marker + GC_OFFSET_BAD)
395 /* We were unable to find anything out about this entry, so
396 * let's investigate it later */
397 u->gc_marker = gc_marker + GC_OFFSET_UNSURE;
398 unit_add_to_gc_queue(u);
402 /* We definitely know that this one is not useful anymore, so
403 * let's mark it for deletion */
404 u->gc_marker = gc_marker + GC_OFFSET_BAD;
405 unit_add_to_cleanup_queue(u);
409 u->gc_marker = gc_marker + GC_OFFSET_GOOD;
412 static unsigned manager_dispatch_gc_queue(Manager *m) {
419 if ((m->n_in_gc_queue < GC_QUEUE_ENTRIES_MAX) &&
420 (m->gc_queue_timestamp <= 0 ||
421 (m->gc_queue_timestamp + GC_QUEUE_USEC_MAX) > now(CLOCK_MONOTONIC)))
424 log_debug("Running GC...");
426 m->gc_marker += _GC_OFFSET_MAX;
427 if (m->gc_marker + _GC_OFFSET_MAX <= _GC_OFFSET_MAX)
430 gc_marker = m->gc_marker;
432 while ((u = m->gc_queue)) {
433 assert(u->in_gc_queue);
435 unit_gc_sweep(u, gc_marker);
437 LIST_REMOVE(Unit, gc_queue, m->gc_queue, u);
438 u->in_gc_queue = false;
442 if (u->gc_marker == gc_marker + GC_OFFSET_BAD ||
443 u->gc_marker == gc_marker + GC_OFFSET_UNSURE) {
444 log_debug("Collecting %s", u->id);
445 u->gc_marker = gc_marker + GC_OFFSET_BAD;
446 unit_add_to_cleanup_queue(u);
450 m->n_in_gc_queue = 0;
451 m->gc_queue_timestamp = 0;
456 static void manager_clear_jobs_and_units(Manager *m) {
461 while ((u = hashmap_first(m->units)))
464 manager_dispatch_cleanup_queue(m);
466 assert(!m->load_queue);
467 assert(!m->run_queue);
468 assert(!m->dbus_unit_queue);
469 assert(!m->dbus_job_queue);
470 assert(!m->cleanup_queue);
471 assert(!m->gc_queue);
473 assert(hashmap_isempty(m->jobs));
474 assert(hashmap_isempty(m->units));
477 void manager_free(Manager *m) {
482 manager_clear_jobs_and_units(m);
484 for (c = 0; c < _UNIT_TYPE_MAX; c++)
485 if (unit_vtable[c]->shutdown)
486 unit_vtable[c]->shutdown(m);
488 /* If we reexecute ourselves, we keep the root cgroup
490 manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE);
492 manager_undo_generators(m);
496 hashmap_free(m->units);
497 hashmap_free(m->jobs);
498 hashmap_free(m->watch_pids);
499 hashmap_free(m->watch_bus);
501 if (m->epoll_fd >= 0)
502 close_nointr_nofail(m->epoll_fd);
503 if (m->signal_watch.fd >= 0)
504 close_nointr_nofail(m->signal_watch.fd);
505 if (m->notify_watch.fd >= 0)
506 close_nointr_nofail(m->notify_watch.fd);
509 if (m->audit_fd >= 0)
510 audit_close(m->audit_fd);
513 free(m->notify_socket);
515 lookup_paths_free(&m->lookup_paths);
516 strv_free(m->environment);
518 strv_free(m->default_controllers);
520 hashmap_free(m->cgroup_bondings);
521 set_free_free(m->unit_path_cache);
523 close_pipe(m->idle_pipe);
525 free(m->switch_root);
526 free(m->switch_root_init);
531 int manager_enumerate(Manager *m) {
537 /* Let's ask every type to load all units from disk/kernel
538 * that it might know */
539 for (c = 0; c < _UNIT_TYPE_MAX; c++)
540 if (unit_vtable[c]->enumerate)
541 if ((q = unit_vtable[c]->enumerate(m)) < 0)
544 manager_dispatch_load_queue(m);
548 int manager_coldplug(Manager *m) {
556 /* Then, let's set up their initial state. */
557 HASHMAP_FOREACH_KEY(u, k, m->units, i) {
563 if ((q = unit_coldplug(u)) < 0)
570 static void manager_build_unit_path_cache(Manager *m) {
577 set_free_free(m->unit_path_cache);
579 if (!(m->unit_path_cache = set_new(string_hash_func, string_compare_func))) {
580 log_error("Failed to allocate unit path cache.");
584 /* This simply builds a list of files we know exist, so that
585 * we don't always have to go to disk */
587 STRV_FOREACH(i, m->lookup_paths.unit_path) {
590 if (!(d = opendir(*i))) {
591 log_error("Failed to open directory: %m");
595 while ((de = readdir(d))) {
598 if (ignore_file(de->d_name))
601 p = join(streq(*i, "/") ? "" : *i, "/", de->d_name, NULL);
607 if ((r = set_put(m->unit_path_cache, p)) < 0) {
620 log_error("Failed to build unit path cache: %s", strerror(-r));
622 set_free_free(m->unit_path_cache);
623 m->unit_path_cache = NULL;
629 int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
634 manager_run_generators(m);
636 manager_build_unit_path_cache(m);
638 /* If we will deserialize make sure that during enumeration
639 * this is already known, so we increase the counter here
644 /* First, enumerate what we can from all config files */
645 r = manager_enumerate(m);
647 /* Second, deserialize if there is something to deserialize */
649 if ((q = manager_deserialize(m, serialization, fds)) < 0)
652 /* Third, fire things up! */
653 if ((q = manager_coldplug(m)) < 0)
657 assert(m->n_reloading > 0);
664 int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, DBusError *e, Job **_ret) {
669 assert(type < _JOB_TYPE_MAX);
671 assert(mode < _JOB_MODE_MAX);
673 if (mode == JOB_ISOLATE && type != JOB_START) {
674 dbus_set_error(e, BUS_ERROR_INVALID_JOB_MODE, "Isolate is only valid for start.");
678 if (mode == JOB_ISOLATE && !unit->allow_isolate) {
679 dbus_set_error(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
683 log_debug("Trying to enqueue job %s/%s/%s", unit->id, job_type_to_string(type), job_mode_to_string(mode));
685 job_type_collapse(&type, unit);
687 tr = transaction_new();
691 r = transaction_add_job_and_dependencies(tr, type, unit, NULL, true, override, false,
692 mode == JOB_IGNORE_DEPENDENCIES || mode == JOB_IGNORE_REQUIREMENTS,
693 mode == JOB_IGNORE_DEPENDENCIES, e);
697 if (mode == JOB_ISOLATE) {
698 r = transaction_add_isolate_jobs(tr, m);
703 r = transaction_activate(tr, m, mode, e);
707 log_debug("Enqueued job %s/%s as %u", unit->id, job_type_to_string(type), (unsigned) tr->anchor_job->id);
710 *_ret = tr->anchor_job;
712 transaction_free(tr);
716 transaction_abort(tr);
717 transaction_free(tr);
721 int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, bool override, DBusError *e, Job **_ret) {
726 assert(type < _JOB_TYPE_MAX);
728 assert(mode < _JOB_MODE_MAX);
730 if ((r = manager_load_unit(m, name, NULL, NULL, &unit)) < 0)
733 return manager_add_job(m, type, unit, mode, override, e, _ret);
736 Job *manager_get_job(Manager *m, uint32_t id) {
739 return hashmap_get(m->jobs, UINT32_TO_PTR(id));
742 Unit *manager_get_unit(Manager *m, const char *name) {
746 return hashmap_get(m->units, name);
749 unsigned manager_dispatch_load_queue(Manager *m) {
755 /* Make sure we are not run recursively */
756 if (m->dispatching_load_queue)
759 m->dispatching_load_queue = true;
761 /* Dispatches the load queue. Takes a unit from the queue and
762 * tries to load its data until the queue is empty */
764 while ((u = m->load_queue)) {
765 assert(u->in_load_queue);
771 m->dispatching_load_queue = false;
775 int manager_load_unit_prepare(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret) {
781 assert(name || path);
783 /* This will prepare the unit for loading, but not actually
784 * load anything from disk. */
786 if (path && !is_path(path)) {
787 dbus_set_error(e, BUS_ERROR_INVALID_PATH, "Path %s is not absolute.", path);
792 name = path_get_file_name(path);
794 t = unit_name_to_type(name);
796 if (t == _UNIT_TYPE_INVALID || !unit_name_is_valid_no_type(name, false)) {
797 dbus_set_error(e, BUS_ERROR_INVALID_NAME, "Unit name %s is not valid.", name);
801 ret = manager_get_unit(m, name);
807 ret = unit_new(m, unit_vtable[t]->object_size);
812 ret->fragment_path = strdup(path);
813 if (!ret->fragment_path) {
819 if ((r = unit_add_name(ret, name)) < 0) {
824 unit_add_to_load_queue(ret);
825 unit_add_to_dbus_queue(ret);
826 unit_add_to_gc_queue(ret);
834 int manager_load_unit(Manager *m, const char *name, const char *path, DBusError *e, Unit **_ret) {
839 /* This will load the service information files, but not actually
840 * start any services or anything. */
842 if ((r = manager_load_unit_prepare(m, name, path, e, _ret)) != 0)
845 manager_dispatch_load_queue(m);
848 *_ret = unit_follow_merge(*_ret);
853 void manager_dump_jobs(Manager *s, FILE *f, const char *prefix) {
860 HASHMAP_FOREACH(j, s->jobs, i)
861 job_dump(j, f, prefix);
864 void manager_dump_units(Manager *s, FILE *f, const char *prefix) {
872 HASHMAP_FOREACH_KEY(u, t, s->units, i)
874 unit_dump(u, f, prefix);
877 void manager_clear_jobs(Manager *m) {
882 while ((j = hashmap_first(m->jobs)))
883 /* No need to recurse. We're cancelling all jobs. */
884 job_finish_and_invalidate(j, JOB_CANCELED, false);
887 unsigned manager_dispatch_run_queue(Manager *m) {
891 if (m->dispatching_run_queue)
894 m->dispatching_run_queue = true;
896 while ((j = m->run_queue)) {
897 assert(j->installed);
898 assert(j->in_run_queue);
900 job_run_and_invalidate(j);
904 m->dispatching_run_queue = false;
908 unsigned manager_dispatch_dbus_queue(Manager *m) {
915 if (m->dispatching_dbus_queue)
918 m->dispatching_dbus_queue = true;
920 while ((u = m->dbus_unit_queue)) {
921 assert(u->in_dbus_queue);
923 bus_unit_send_change_signal(u);
927 while ((j = m->dbus_job_queue)) {
928 assert(j->in_dbus_queue);
930 bus_job_send_change_signal(j);
934 m->dispatching_dbus_queue = false;
938 static int manager_process_notify_fd(Manager *m) {
945 struct msghdr msghdr;
949 struct cmsghdr cmsghdr;
950 uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
956 iovec.iov_base = buf;
957 iovec.iov_len = sizeof(buf)-1;
961 msghdr.msg_iov = &iovec;
962 msghdr.msg_iovlen = 1;
963 msghdr.msg_control = &control;
964 msghdr.msg_controllen = sizeof(control);
966 if ((n = recvmsg(m->notify_watch.fd, &msghdr, MSG_DONTWAIT)) <= 0) {
970 if (errno == EAGAIN || errno == EINTR)
976 if (msghdr.msg_controllen < CMSG_LEN(sizeof(struct ucred)) ||
977 control.cmsghdr.cmsg_level != SOL_SOCKET ||
978 control.cmsghdr.cmsg_type != SCM_CREDENTIALS ||
979 control.cmsghdr.cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
980 log_warning("Received notify message without credentials. Ignoring.");
984 ucred = (struct ucred*) CMSG_DATA(&control.cmsghdr);
986 if (!(u = hashmap_get(m->watch_pids, LONG_TO_PTR(ucred->pid))))
987 if (!(u = cgroup_unit_by_pid(m, ucred->pid))) {
988 log_warning("Cannot find unit for notify message of PID %lu.", (unsigned long) ucred->pid);
992 assert((size_t) n < sizeof(buf));
994 if (!(tags = strv_split(buf, "\n\r")))
997 log_debug("Got notification message for unit %s", u->id);
999 if (UNIT_VTABLE(u)->notify_message)
1000 UNIT_VTABLE(u)->notify_message(u, ucred->pid, tags);
1008 static int manager_dispatch_sigchld(Manager *m) {
1018 /* First we call waitd() for a PID and do not reap the
1019 * zombie. That way we can still access /proc/$PID for
1020 * it while it is a zombie. */
1021 if (waitid(P_ALL, 0, &si, WEXITED|WNOHANG|WNOWAIT) < 0) {
1023 if (errno == ECHILD)
1035 if (si.si_code == CLD_EXITED || si.si_code == CLD_KILLED || si.si_code == CLD_DUMPED) {
1038 get_process_comm(si.si_pid, &name);
1039 log_debug("Got SIGCHLD for process %lu (%s)", (unsigned long) si.si_pid, strna(name));
1043 /* Let's flush any message the dying child might still
1044 * have queued for us. This ensures that the process
1045 * still exists in /proc so that we can figure out
1046 * which cgroup and hence unit it belongs to. */
1047 if ((r = manager_process_notify_fd(m)) < 0)
1050 /* And now figure out the unit this belongs to */
1051 if (!(u = hashmap_get(m->watch_pids, LONG_TO_PTR(si.si_pid))))
1052 u = cgroup_unit_by_pid(m, si.si_pid);
1054 /* And now, we actually reap the zombie. */
1055 if (waitid(P_PID, si.si_pid, &si, WEXITED) < 0) {
1062 if (si.si_code != CLD_EXITED && si.si_code != CLD_KILLED && si.si_code != CLD_DUMPED)
1065 log_debug("Child %lu died (code=%s, status=%i/%s)",
1066 (long unsigned) si.si_pid,
1067 sigchld_code_to_string(si.si_code),
1069 strna(si.si_code == CLD_EXITED
1070 ? exit_status_to_string(si.si_status, EXIT_STATUS_FULL)
1071 : signal_to_string(si.si_status)));
1076 log_debug("Child %lu belongs to %s", (long unsigned) si.si_pid, u->id);
1078 hashmap_remove(m->watch_pids, LONG_TO_PTR(si.si_pid));
1079 UNIT_VTABLE(u)->sigchld_event(u, si.si_pid, si.si_code, si.si_status);
1085 static int manager_start_target(Manager *m, const char *name, JobMode mode) {
1089 dbus_error_init(&error);
1091 log_debug("Activating special unit %s", name);
1093 if ((r = manager_add_job_by_name(m, JOB_START, name, mode, true, &error, NULL)) < 0)
1094 log_error("Failed to enqueue %s job: %s", name, bus_error(&error, r));
1096 dbus_error_free(&error);
1101 static int manager_process_signal_fd(Manager *m) {
1103 struct signalfd_siginfo sfsi;
1104 bool sigchld = false;
1109 if ((n = read(m->signal_watch.fd, &sfsi, sizeof(sfsi))) != sizeof(sfsi)) {
1114 if (errno == EINTR || errno == EAGAIN)
1120 if (sfsi.ssi_pid > 0) {
1123 get_process_comm(sfsi.ssi_pid, &p);
1125 log_debug("Received SIG%s from PID %lu (%s).",
1126 signal_to_string(sfsi.ssi_signo),
1127 (unsigned long) sfsi.ssi_pid, strna(p));
1130 log_debug("Received SIG%s.", signal_to_string(sfsi.ssi_signo));
1132 switch (sfsi.ssi_signo) {
1139 if (m->running_as == MANAGER_SYSTEM) {
1140 /* This is for compatibility with the
1141 * original sysvinit */
1142 m->exit_code = MANAGER_REEXECUTE;
1149 if (m->running_as == MANAGER_SYSTEM) {
1150 manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE);
1154 /* Run the exit target if there is one, if not, just exit. */
1155 if (manager_start_target(m, SPECIAL_EXIT_TARGET, JOB_REPLACE) < 0) {
1156 m->exit_code = MANAGER_EXIT;
1163 if (m->running_as == MANAGER_SYSTEM)
1164 manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE);
1166 /* This is a nop on non-init */
1170 if (m->running_as == MANAGER_SYSTEM)
1171 manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE);
1173 /* This is a nop on non-init */
1179 u = manager_get_unit(m, SPECIAL_DBUS_SERVICE);
1181 if (!u || UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) {
1182 log_info("Trying to reconnect to bus...");
1186 if (!u || !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) {
1187 log_info("Loading D-Bus service...");
1188 manager_start_target(m, SPECIAL_DBUS_SERVICE, JOB_REPLACE);
1199 if (!(f = open_memstream(&dump, &size))) {
1200 log_warning("Failed to allocate memory stream.");
1204 manager_dump_units(m, f, "\t");
1205 manager_dump_jobs(m, f, "\t");
1210 log_warning("Failed to write status stream");
1215 log_dump(LOG_INFO, dump);
1222 m->exit_code = MANAGER_RELOAD;
1227 /* Starting SIGRTMIN+0 */
1228 static const char * const target_table[] = {
1229 [0] = SPECIAL_DEFAULT_TARGET,
1230 [1] = SPECIAL_RESCUE_TARGET,
1231 [2] = SPECIAL_EMERGENCY_TARGET,
1232 [3] = SPECIAL_HALT_TARGET,
1233 [4] = SPECIAL_POWEROFF_TARGET,
1234 [5] = SPECIAL_REBOOT_TARGET,
1235 [6] = SPECIAL_KEXEC_TARGET
1238 /* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */
1239 static const ManagerExitCode code_table[] = {
1241 [1] = MANAGER_POWEROFF,
1242 [2] = MANAGER_REBOOT,
1246 if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
1247 (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) {
1248 int idx = (int) sfsi.ssi_signo - SIGRTMIN;
1249 manager_start_target(m, target_table[idx],
1250 (idx == 1 || idx == 2) ? JOB_ISOLATE : JOB_REPLACE);
1254 if ((int) sfsi.ssi_signo >= SIGRTMIN+13 &&
1255 (int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(code_table)) {
1256 m->exit_code = code_table[sfsi.ssi_signo - SIGRTMIN - 13];
1260 switch (sfsi.ssi_signo - SIGRTMIN) {
1263 log_debug("Enabling showing of status.");
1264 manager_set_show_status(m, true);
1268 log_debug("Disabling showing of status.");
1269 manager_set_show_status(m, false);
1273 log_set_max_level(LOG_DEBUG);
1274 log_notice("Setting log level to debug.");
1278 log_set_max_level(LOG_INFO);
1279 log_notice("Setting log level to info.");
1283 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1284 log_notice("Setting log target to journal-or-kmsg.");
1288 log_set_target(LOG_TARGET_CONSOLE);
1289 log_notice("Setting log target to console.");
1293 log_set_target(LOG_TARGET_KMSG);
1294 log_notice("Setting log target to kmsg.");
1298 log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
1299 log_notice("Setting log target to syslog-or-kmsg.");
1303 log_warning("Got unhandled signal <%s>.", signal_to_string(sfsi.ssi_signo));
1310 return manager_dispatch_sigchld(m);
1315 static int process_event(Manager *m, struct epoll_event *ev) {
1322 assert_se(w = ev->data.ptr);
1324 if (w->type == WATCH_INVALID)
1331 /* An incoming signal? */
1332 if (ev->events != EPOLLIN)
1335 if ((r = manager_process_signal_fd(m)) < 0)
1342 /* An incoming daemon notification event? */
1343 if (ev->events != EPOLLIN)
1346 if ((r = manager_process_notify_fd(m)) < 0)
1353 /* Some fd event, to be dispatched to the units */
1354 UNIT_VTABLE(w->data.unit)->fd_event(w->data.unit, w->fd, ev->events, w);
1357 case WATCH_UNIT_TIMER:
1358 case WATCH_JOB_TIMER: {
1362 /* Some timer event, to be dispatched to the units */
1363 if ((k = read(w->fd, &v, sizeof(v))) != sizeof(v)) {
1365 if (k < 0 && (errno == EINTR || errno == EAGAIN))
1368 return k < 0 ? -errno : -EIO;
1371 if (w->type == WATCH_UNIT_TIMER)
1372 UNIT_VTABLE(w->data.unit)->timer_event(w->data.unit, v, w);
1374 job_timer_event(w->data.job, v, w);
1379 /* Some mount table change, intended for the mount subsystem */
1380 mount_fd_event(m, ev->events);
1384 /* Some swap table change, intended for the swap subsystem */
1385 swap_fd_event(m, ev->events);
1389 /* Some notification from udev, intended for the device subsystem */
1390 device_fd_event(m, ev->events);
1393 case WATCH_DBUS_WATCH:
1394 bus_watch_event(m, w, ev->events);
1397 case WATCH_DBUS_TIMEOUT:
1398 bus_timeout_event(m, w, ev->events);
1402 log_error("event type=%i", w->type);
1403 assert_not_reached("Unknown epoll event type.");
1409 int manager_loop(Manager *m) {
1412 RATELIMIT_DEFINE(rl, 1*USEC_PER_SEC, 50000);
1415 m->exit_code = MANAGER_RUNNING;
1417 /* Release the path cache */
1418 set_free_free(m->unit_path_cache);
1419 m->unit_path_cache = NULL;
1421 manager_check_finished(m);
1423 /* There might still be some zombies hanging around from
1424 * before we were exec()'ed. Leat's reap them */
1425 r = manager_dispatch_sigchld(m);
1429 while (m->exit_code == MANAGER_RUNNING) {
1430 struct epoll_event event;
1434 if (m->runtime_watchdog > 0 && m->running_as == MANAGER_SYSTEM)
1437 if (!ratelimit_test(&rl)) {
1438 /* Yay, something is going seriously wrong, pause a little */
1439 log_warning("Looping too fast. Throttling execution a little.");
1444 if (manager_dispatch_load_queue(m) > 0)
1447 if (manager_dispatch_run_queue(m) > 0)
1450 if (bus_dispatch(m) > 0)
1453 if (manager_dispatch_cleanup_queue(m) > 0)
1456 if (manager_dispatch_gc_queue(m) > 0)
1459 if (manager_dispatch_dbus_queue(m) > 0)
1462 if (swap_dispatch_reload(m) > 0)
1465 /* Sleep for half the watchdog time */
1466 if (m->runtime_watchdog > 0 && m->running_as == MANAGER_SYSTEM) {
1467 wait_msec = (int) (m->runtime_watchdog / 2 / USEC_PER_MSEC);
1473 n = epoll_wait(m->epoll_fd, &event, 1, wait_msec);
1485 r = process_event(m, &event);
1490 return m->exit_code;
1493 int manager_load_unit_from_dbus_path(Manager *m, const char *s, DBusError *e, Unit **_u) {
1502 if (!startswith(s, "/org/freedesktop/systemd1/unit/"))
1505 n = bus_path_unescape(s+31);
1509 r = manager_load_unit(m, n, NULL, e, &u);
1520 int manager_get_job_from_dbus_path(Manager *m, const char *s, Job **_j) {
1529 if (!startswith(s, "/org/freedesktop/systemd1/job/"))
1532 if ((r = safe_atou(s + 30, &id)) < 0)
1535 if (!(j = manager_get_job(m, id)))
1543 void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
1548 if (m->audit_fd < 0)
1551 /* Don't generate audit events if the service was already
1552 * started and we're just deserializing */
1553 if (m->n_reloading > 0)
1556 if (m->running_as != MANAGER_SYSTEM)
1559 if (u->type != UNIT_SERVICE)
1562 if (!(p = unit_name_to_prefix_and_instance(u->id))) {
1563 log_error("Failed to allocate unit name for audit message: %s", strerror(ENOMEM));
1567 if (audit_log_user_comm_message(m->audit_fd, type, "", p, NULL, NULL, NULL, success) < 0) {
1568 if (errno == EPERM) {
1569 /* We aren't allowed to send audit messages?
1570 * Then let's not retry again. */
1571 audit_close(m->audit_fd);
1574 log_warning("Failed to send audit message: %m");
1582 void manager_send_unit_plymouth(Manager *m, Unit *u) {
1584 union sockaddr_union sa;
1586 char *message = NULL;
1588 /* Don't generate plymouth events if the service was already
1589 * started and we're just deserializing */
1590 if (m->n_reloading > 0)
1593 if (m->running_as != MANAGER_SYSTEM)
1596 if (u->type != UNIT_SERVICE &&
1597 u->type != UNIT_MOUNT &&
1598 u->type != UNIT_SWAP)
1601 /* We set SOCK_NONBLOCK here so that we rather drop the
1602 * message then wait for plymouth */
1603 if ((fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0)) < 0) {
1604 log_error("socket() failed: %m");
1609 sa.sa.sa_family = AF_UNIX;
1610 strncpy(sa.un.sun_path+1, "/org/freedesktop/plymouthd", sizeof(sa.un.sun_path)-1);
1611 if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(sa.un.sun_path+1)) < 0) {
1613 if (errno != EPIPE &&
1616 errno != ECONNREFUSED &&
1617 errno != ECONNRESET &&
1618 errno != ECONNABORTED)
1619 log_error("connect() failed: %m");
1624 if (asprintf(&message, "U\002%c%s%n", (int) (strlen(u->id) + 1), u->id, &n) < 0) {
1625 log_error("Out of memory");
1630 if (write(fd, message, n + 1) != n + 1) {
1632 if (errno != EPIPE &&
1635 errno != ECONNREFUSED &&
1636 errno != ECONNRESET &&
1637 errno != ECONNABORTED)
1638 log_error("Failed to write Plymouth message: %m");
1645 close_nointr_nofail(fd);
1650 void manager_dispatch_bus_name_owner_changed(
1653 const char* old_owner,
1654 const char *new_owner) {
1661 if (!(u = hashmap_get(m->watch_bus, name)))
1664 UNIT_VTABLE(u)->bus_name_owner_change(u, name, old_owner, new_owner);
1667 void manager_dispatch_bus_query_pid_done(
1678 if (!(u = hashmap_get(m->watch_bus, name)))
1681 UNIT_VTABLE(u)->bus_query_pid_done(u, name, pid);
1684 int manager_open_serialization(Manager *m, FILE **_f) {
1692 if (m->running_as == MANAGER_SYSTEM)
1693 asprintf(&path, "/run/systemd/dump-%lu-XXXXXX", (unsigned long) getpid());
1695 asprintf(&path, "/tmp/systemd-dump-%lu-XXXXXX", (unsigned long) getpid());
1700 saved_umask = umask(0077);
1701 fd = mkostemp(path, O_RDWR|O_CLOEXEC);
1711 log_debug("Serializing state to %s", path);
1714 if (!(f = fdopen(fd, "w+")))
1722 int manager_serialize(Manager *m, FILE *f, FDSet *fds) {
1734 fprintf(f, "current-job-id=%i\n", m->current_job_id);
1735 fprintf(f, "taint-usr=%s\n", yes_no(m->taint_usr));
1737 dual_timestamp_serialize(f, "initrd-timestamp", &m->initrd_timestamp);
1739 if (! in_initrd()) {
1740 dual_timestamp_serialize(f, "startup-timestamp", &m->startup_timestamp);
1741 dual_timestamp_serialize(f, "finish-timestamp", &m->finish_timestamp);
1746 HASHMAP_FOREACH_KEY(u, t, m->units, i) {
1750 if (!unit_can_serialize(u))
1757 if ((r = unit_serialize(u, f, fds)) < 0) {
1763 assert(m->n_reloading > 0);
1769 r = bus_fdset_add_all(m, fds);
1776 int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
1782 log_debug("Deserializing state...");
1787 char line[LINE_MAX], *l;
1789 if (!fgets(line, sizeof(line), f)) {
1804 if (startswith(l, "current-job-id=")) {
1807 if (safe_atou32(l+15, &id) < 0)
1808 log_debug("Failed to parse current job id value %s", l+15);
1810 m->current_job_id = MAX(m->current_job_id, id);
1811 } else if (startswith(l, "taint-usr=")) {
1814 if ((b = parse_boolean(l+10)) < 0)
1815 log_debug("Failed to parse taint /usr flag %s", l+10);
1817 m->taint_usr = m->taint_usr || b;
1818 } else if (startswith(l, "initrd-timestamp="))
1819 dual_timestamp_deserialize(l+17, &m->initrd_timestamp);
1820 else if (startswith(l, "startup-timestamp="))
1821 dual_timestamp_deserialize(l+18, &m->startup_timestamp);
1822 else if (startswith(l, "finish-timestamp="))
1823 dual_timestamp_deserialize(l+17, &m->finish_timestamp);
1825 log_debug("Unknown serialization item '%s'", l);
1830 char name[UNIT_NAME_MAX+2];
1833 if (!fgets(name, sizeof(name), f)) {
1844 if ((r = manager_load_unit(m, strstrip(name), NULL, NULL, &u)) < 0)
1847 if ((r = unit_deserialize(u, f, fds)) < 0)
1857 assert(m->n_reloading > 0);
1863 int manager_reload(Manager *m) {
1870 if ((r = manager_open_serialization(m, &f)) < 0)
1875 if (!(fds = fdset_new())) {
1881 if ((r = manager_serialize(m, f, fds)) < 0) {
1886 if (fseeko(f, 0, SEEK_SET) < 0) {
1892 /* From here on there is no way back. */
1893 manager_clear_jobs_and_units(m);
1894 manager_undo_generators(m);
1896 /* Find new unit paths */
1897 lookup_paths_free(&m->lookup_paths);
1898 if ((q = lookup_paths_init(&m->lookup_paths, m->running_as, true)) < 0)
1901 manager_run_generators(m);
1903 manager_build_unit_path_cache(m);
1905 /* First, enumerate what we can from all config files */
1906 if ((q = manager_enumerate(m)) < 0)
1909 /* Second, deserialize our stored data */
1910 if ((q = manager_deserialize(m, f, fds)) < 0)
1916 /* Third, fire things up! */
1917 if ((q = manager_coldplug(m)) < 0)
1920 assert(m->n_reloading > 0);
1933 bool manager_is_booting_or_shutting_down(Manager *m) {
1938 /* Is the initial job still around? */
1939 if (manager_get_job(m, m->default_unit_job_id))
1942 /* Is there a job for the shutdown target? */
1943 u = manager_get_unit(m, SPECIAL_SHUTDOWN_TARGET);
1950 void manager_reset_failed(Manager *m) {
1956 HASHMAP_FOREACH(u, m->units, i)
1957 unit_reset_failed(u);
1960 bool manager_unit_pending_inactive(Manager *m, const char *name) {
1966 /* Returns true if the unit is inactive or going down */
1967 if (!(u = manager_get_unit(m, name)))
1970 return unit_pending_inactive(u);
1973 void manager_check_finished(Manager *m) {
1974 char userspace[FORMAT_TIMESPAN_MAX], initrd[FORMAT_TIMESPAN_MAX], kernel[FORMAT_TIMESPAN_MAX], sum[FORMAT_TIMESPAN_MAX];
1975 usec_t kernel_usec, initrd_usec, userspace_usec, total_usec;
1979 if (hashmap_size(m->jobs) > 0)
1982 /* Notify Type=idle units that we are done now */
1983 close_pipe(m->idle_pipe);
1985 if (dual_timestamp_is_set(&m->finish_timestamp))
1988 dual_timestamp_get(&m->finish_timestamp);
1990 if (m->running_as == MANAGER_SYSTEM && detect_container(NULL) <= 0) {
1992 userspace_usec = m->finish_timestamp.monotonic - m->startup_timestamp.monotonic;
1993 total_usec = m->finish_timestamp.monotonic;
1995 if (dual_timestamp_is_set(&m->initrd_timestamp)) {
1997 kernel_usec = m->initrd_timestamp.monotonic;
1998 initrd_usec = m->startup_timestamp.monotonic - m->initrd_timestamp.monotonic;
2000 log_info("Startup finished in %s (kernel) + %s (initrd) + %s (userspace) = %s.",
2001 format_timespan(kernel, sizeof(kernel), kernel_usec),
2002 format_timespan(initrd, sizeof(initrd), initrd_usec),
2003 format_timespan(userspace, sizeof(userspace), userspace_usec),
2004 format_timespan(sum, sizeof(sum), total_usec));
2006 kernel_usec = m->startup_timestamp.monotonic;
2009 log_info("Startup finished in %s (kernel) + %s (userspace) = %s.",
2010 format_timespan(kernel, sizeof(kernel), kernel_usec),
2011 format_timespan(userspace, sizeof(userspace), userspace_usec),
2012 format_timespan(sum, sizeof(sum), total_usec));
2015 userspace_usec = initrd_usec = kernel_usec = 0;
2016 total_usec = m->finish_timestamp.monotonic - m->startup_timestamp.monotonic;
2018 log_debug("Startup finished in %s.",
2019 format_timespan(sum, sizeof(sum), total_usec));
2022 bus_broadcast_finished(m, kernel_usec, initrd_usec, userspace_usec, total_usec);
2025 "READY=1\nSTATUS=Startup finished in %s.",
2026 format_timespan(sum, sizeof(sum), total_usec));
2029 void manager_run_generators(Manager *m) {
2031 const char *generator_path;
2032 const char *argv[3];
2037 generator_path = m->running_as == MANAGER_SYSTEM ? SYSTEM_GENERATOR_PATH : USER_GENERATOR_PATH;
2038 if (!(d = opendir(generator_path))) {
2040 if (errno == ENOENT)
2043 log_error("Failed to enumerate generator directory: %m");
2047 if (!m->generator_unit_path) {
2049 char user_path[] = "/tmp/systemd-generator-XXXXXX";
2051 if (m->running_as == MANAGER_SYSTEM && getpid() == 1) {
2052 p = "/run/systemd/generator";
2054 if (mkdir_p(p, 0755) < 0) {
2055 log_error("Failed to create generator directory: %m");
2060 if (!(p = mkdtemp(user_path))) {
2061 log_error("Failed to create generator directory: %m");
2066 if (!(m->generator_unit_path = strdup(p))) {
2067 log_error("Failed to allocate generator unit path.");
2072 argv[0] = NULL; /* Leave this empty, execute_directory() will fill something in */
2073 argv[1] = m->generator_unit_path;
2077 execute_directory(generator_path, d, (char**) argv);
2080 if (rmdir(m->generator_unit_path) >= 0) {
2081 /* Uh? we were able to remove this dir? I guess that
2082 * means the directory was empty, hence let's shortcut
2085 free(m->generator_unit_path);
2086 m->generator_unit_path = NULL;
2090 if (!strv_find(m->lookup_paths.unit_path, m->generator_unit_path)) {
2093 if (!(l = strv_append(m->lookup_paths.unit_path, m->generator_unit_path))) {
2094 log_error("Failed to add generator directory to unit search path: %m");
2098 strv_free(m->lookup_paths.unit_path);
2099 m->lookup_paths.unit_path = l;
2101 log_debug("Added generator unit path %s to search path.", m->generator_unit_path);
2109 void manager_undo_generators(Manager *m) {
2112 if (!m->generator_unit_path)
2115 strv_remove(m->lookup_paths.unit_path, m->generator_unit_path);
2116 rm_rf(m->generator_unit_path, false, true, false);
2118 free(m->generator_unit_path);
2119 m->generator_unit_path = NULL;
2122 int manager_set_default_controllers(Manager *m, char **controllers) {
2127 l = strv_copy(controllers);
2131 strv_free(m->default_controllers);
2132 m->default_controllers = l;
2134 cg_shorten_controllers(m->default_controllers);
2139 void manager_recheck_journal(Manager *m) {
2144 if (m->running_as != MANAGER_SYSTEM)
2147 u = manager_get_unit(m, SPECIAL_JOURNALD_SOCKET);
2148 if (u && SOCKET(u)->state != SOCKET_RUNNING) {
2149 log_close_journal();
2153 u = manager_get_unit(m, SPECIAL_JOURNALD_SERVICE);
2154 if (u && SERVICE(u)->state != SERVICE_RUNNING) {
2155 log_close_journal();
2159 /* Hmm, OK, so the socket is fully up and the service is up
2160 * too, then let's make use of the thing. */
2164 void manager_set_show_status(Manager *m, bool b) {
2167 if (m->running_as != MANAGER_SYSTEM)
2173 touch("/run/systemd/show-status");
2175 unlink("/run/systemd/show-status");
2178 bool manager_get_show_status(Manager *m) {
2181 if (m->running_as != MANAGER_SYSTEM)
2187 /* If Plymouth is running make sure we show the status, so
2188 * that there's something nice to see when people press Esc */
2190 return plymouth_running();
2193 static const char* const manager_running_as_table[_MANAGER_RUNNING_AS_MAX] = {
2194 [MANAGER_SYSTEM] = "system",
2195 [MANAGER_USER] = "user"
2198 DEFINE_STRING_TABLE_LOOKUP(manager_running_as, ManagerRunningAs);