diff options
Diffstat (limited to 'src/core/manager.c')
-rw-r--r-- | src/core/manager.c | 282 |
1 files changed, 135 insertions, 147 deletions
diff --git a/src/core/manager.c b/src/core/manager.c index 9bfe867ea0..b13663e702 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -19,19 +19,19 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <dirent.h> #include <errno.h> -#include <string.h> +#include <fcntl.h> +#include <linux/kd.h> #include <signal.h> -#include <sys/wait.h> -#include <unistd.h> -#include <sys/inotify.h> +#include <string.h> #include <sys/epoll.h> -#include <sys/reboot.h> +#include <sys/inotify.h> #include <sys/ioctl.h> -#include <linux/kd.h> -#include <fcntl.h> -#include <dirent.h> +#include <sys/reboot.h> #include <sys/timerfd.h> +#include <sys/wait.h> +#include <unistd.h> #ifdef HAVE_AUDIT #include <libaudit.h> @@ -40,40 +40,53 @@ #include "sd-daemon.h" #include "sd-messages.h" -#include "hashmap.h" -#include "macro.h" -#include "strv.h" -#include "log.h" -#include "util.h" -#include "mkdir.h" -#include "ratelimit.h" -#include "locale-setup.h" -#include "unit-name.h" -#include "missing.h" -#include "rm-rf.h" -#include "path-lookup.h" -#include "special.h" -#include "exit-status.h" -#include "virt.h" -#include "watchdog.h" -#include "path-util.h" +#include "alloc-util.h" #include "audit-fd.h" #include "boot-timestamps.h" -#include "env-util.h" #include "bus-common-errors.h" #include "bus-error.h" -#include "bus-util.h" #include "bus-kernel.h" -#include "time-util.h" -#include "process-util.h" -#include "terminal-util.h" -#include "signal-util.h" -#include "dbus.h" -#include "dbus-unit.h" +#include "bus-util.h" #include "dbus-job.h" #include "dbus-manager.h" +#include "dbus-unit.h" +#include "dbus.h" +#include "env-util.h" +#include "escape.h" +#include "exit-status.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "hashmap.h" +#include "io-util.h" +#include "locale-setup.h" +#include "log.h" +#include "macro.h" #include "manager.h" +#include "missing.h" +#include "mkdir.h" +#include "parse-util.h" +#include "path-lookup.h" +#include "path-util.h" +#include "process-util.h" +#include "ratelimit.h" +#include "rm-rf.h" +#include "signal-util.h" +#include "special.h" +#include "stat-util.h" +#include "string-table.h" +#include "string-util.h" +#include "strv.h" +#include "terminal-util.h" +#include "time-util.h" #include "transaction.h" +#include "umask-util.h" +#include "unit-name.h" +#include "util.h" +#include "virt.h" +#include "watchdog.h" + +#define NOTIFY_RCVBUF_SIZE (8*1024*1024) /* Initial delay and the interval for printing status messages about running jobs */ #define JOBS_IN_PROGRESS_WAIT_USEC (5*USEC_PER_SEC) @@ -495,6 +508,7 @@ static void manager_clean_environment(Manager *m) { "MANAGERPID", "LISTEN_PID", "LISTEN_FDS", + "LISTEN_FDNAMES", "WATCHDOG_PID", "WATCHDOG_USEC", NULL); @@ -677,6 +691,8 @@ static int manager_setup_notify(Manager *m) { if (fd < 0) return log_error_errno(errno, "Failed to allocate notification socket: %m"); + fd_inc_rcvbuf(fd, NOTIFY_RCVBUF_SIZE); + if (m->running_as == MANAGER_SYSTEM) m->notify_socket = strdup("/run/systemd/notify"); else { @@ -1476,7 +1492,7 @@ static unsigned manager_dispatch_dbus_queue(Manager *m) { return n; } -static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, char *buf, size_t n, FDSet *fds) { +static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, const char *buf, size_t n, FDSet *fds) { _cleanup_strv_free_ char **tags = NULL; assert(m); @@ -1497,9 +1513,33 @@ static void manager_invoke_notify_message(Manager *m, Unit *u, pid_t pid, char * } static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { + _cleanup_fdset_free_ FDSet *fds = NULL; Manager *m = userdata; + + char buf[NOTIFY_BUFFER_MAX+1]; + struct iovec iovec = { + .iov_base = buf, + .iov_len = sizeof(buf)-1, + }; + union { + struct cmsghdr cmsghdr; + uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) + + CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)]; + } control = {}; + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + + struct cmsghdr *cmsg; + struct ucred *ucred = NULL; + bool found = false; + Unit *u1, *u2, *u3; + int r, *fd_array = NULL; + unsigned n_fds = 0; ssize_t n; - int r; assert(m); assert(m->notify_fd == fd); @@ -1509,106 +1549,80 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t return 0; } - for (;;) { - _cleanup_fdset_free_ FDSet *fds = NULL; - char buf[NOTIFY_BUFFER_MAX+1]; - struct iovec iovec = { - .iov_base = buf, - .iov_len = sizeof(buf)-1, - }; - union { - struct cmsghdr cmsghdr; - uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) + - CMSG_SPACE(sizeof(int) * NOTIFY_FD_MAX)]; - } control = {}; - struct msghdr msghdr = { - .msg_iov = &iovec, - .msg_iovlen = 1, - .msg_control = &control, - .msg_controllen = sizeof(control), - }; - struct cmsghdr *cmsg; - struct ucred *ucred = NULL; - bool found = false; - Unit *u1, *u2, *u3; - int *fd_array = NULL; - unsigned n_fds = 0; - - n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); - if (n < 0) { - if (errno == EAGAIN || errno == EINTR) - break; + n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (n < 0) { + if (errno == EAGAIN || errno == EINTR) + return 0; - return -errno; - } + return -errno; + } - CMSG_FOREACH(cmsg, &msghdr) { - if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { + CMSG_FOREACH(cmsg, &msghdr) { + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { - fd_array = (int*) CMSG_DATA(cmsg); - n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); + fd_array = (int*) CMSG_DATA(cmsg); + n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int); - } else if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { + } else if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDENTIALS && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { - ucred = (struct ucred*) CMSG_DATA(cmsg); - } + ucred = (struct ucred*) CMSG_DATA(cmsg); } + } - if (n_fds > 0) { - assert(fd_array); + if (n_fds > 0) { + assert(fd_array); - r = fdset_new_array(&fds, fd_array, n_fds); - if (r < 0) { - close_many(fd_array, n_fds); - return log_oom(); - } + r = fdset_new_array(&fds, fd_array, n_fds); + if (r < 0) { + close_many(fd_array, n_fds); + return log_oom(); } + } - if (!ucred || ucred->pid <= 0) { - log_warning("Received notify message without valid credentials. Ignoring."); - continue; - } + if (!ucred || ucred->pid <= 0) { + log_warning("Received notify message without valid credentials. Ignoring."); + return 0; + } - if ((size_t) n >= sizeof(buf)) { - log_warning("Received notify message exceeded maximum size. Ignoring."); - continue; - } + if ((size_t) n >= sizeof(buf)) { + log_warning("Received notify message exceeded maximum size. Ignoring."); + return 0; + } - buf[n] = 0; + buf[n] = 0; - /* Notify every unit that might be interested, but try - * to avoid notifying the same one multiple times. */ - u1 = manager_get_unit_by_pid_cgroup(m, ucred->pid); - if (u1) { - manager_invoke_notify_message(m, u1, ucred->pid, buf, n, fds); - found = true; - } + /* Notify every unit that might be interested, but try + * to avoid notifying the same one multiple times. */ + u1 = manager_get_unit_by_pid_cgroup(m, ucred->pid); + if (u1) { + manager_invoke_notify_message(m, u1, ucred->pid, buf, n, fds); + found = true; + } - u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(ucred->pid)); - if (u2 && u2 != u1) { - manager_invoke_notify_message(m, u2, ucred->pid, buf, n, fds); - found = true; - } + u2 = hashmap_get(m->watch_pids1, PID_TO_PTR(ucred->pid)); + if (u2 && u2 != u1) { + manager_invoke_notify_message(m, u2, ucred->pid, buf, n, fds); + found = true; + } - u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(ucred->pid)); - if (u3 && u3 != u2 && u3 != u1) { - manager_invoke_notify_message(m, u3, ucred->pid, buf, n, fds); - found = true; - } + u3 = hashmap_get(m->watch_pids2, PID_TO_PTR(ucred->pid)); + if (u3 && u3 != u2 && u3 != u1) { + manager_invoke_notify_message(m, u3, ucred->pid, buf, n, fds); + found = true; + } - if (!found) - log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid); + if (!found) + log_warning("Cannot find unit for notify message of PID "PID_FMT".", ucred->pid); - if (fdset_size(fds) > 0) - log_warning("Got auxiliary fds with notification message, closing all."); - } + if (fdset_size(fds) > 0) + log_warning("Got auxiliary fds with notification message, closing all."); return 0; } -static void invoke_sigchld_event(Manager *m, Unit *u, siginfo_t *si) { +static void invoke_sigchld_event(Manager *m, Unit *u, const siginfo_t *si) { assert(m); assert(u); assert(si); @@ -1990,8 +2004,7 @@ int manager_loop(Manager *m) { m->exit_code = MANAGER_OK; /* Release the path cache */ - set_free_free(m->unit_path_cache); - m->unit_path_cache = NULL; + m->unit_path_cache = set_free_free(m->unit_path_cache); manager_check_finished(m); @@ -2101,6 +2114,9 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) { const char *msg; int audit_fd, r; + if (m->running_as != MANAGER_SYSTEM) + return; + audit_fd = get_audit_fd(); if (audit_fd < 0) return; @@ -2110,9 +2126,6 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) { if (m->n_reloading > 0) return; - if (m->running_as != MANAGER_SYSTEM) - return; - if (u->type != UNIT_SERVICE) return; @@ -2761,8 +2774,7 @@ static int create_generator_dir(Manager *m, char **generator, const char *name) return log_oom(); if (!mkdtemp(p)) { - log_error_errno(errno, "Failed to create generator directory %s: %m", - p); + log_error_errno(errno, "Failed to create generator directory %s: %m", p); free(p); return -errno; } @@ -2951,9 +2963,9 @@ void manager_set_show_status(Manager *m, ShowStatus mode) { m->show_status = mode; if (mode > 0) - touch("/run/systemd/show-status"); + (void) touch("/run/systemd/show-status"); else - unlink("/run/systemd/show-status"); + (void) unlink("/run/systemd/show-status"); } static bool manager_get_show_status(Manager *m, StatusType type) { @@ -3012,30 +3024,6 @@ void manager_status_printf(Manager *m, StatusType type, const char *status, cons va_end(ap); } -int manager_get_unit_by_path(Manager *m, const char *path, const char *suffix, Unit **_found) { - _cleanup_free_ char *p = NULL; - Unit *found; - int r; - - assert(m); - assert(path); - assert(suffix); - assert(_found); - - r = unit_name_from_path(path, suffix, &p); - if (r < 0) - return r; - - found = manager_get_unit(m, p); - if (!found) { - *_found = NULL; - return 0; - } - - *_found = found; - return 1; -} - Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path) { char p[strlen(path)+1]; |