#include "log.h"
#include "macro.h"
#include "manager.h"
+#include "memory-util.h"
#include "missing.h"
#include "mkdir.h"
#include "parse-util.h"
#include "path-lookup.h"
#include "path-util.h"
+#include "plymouth-util.h"
#include "process-util.h"
#include "ratelimit.h"
#include "rlimit-util.h"
#include "umask-util.h"
#include "unit-name.h"
#include "user-util.h"
-#include "util.h"
#include "virt.h"
#include "watchdog.h"
m->ask_password_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
if (m->ask_password_inotify_fd < 0)
- return log_error_errno(errno, "inotify_init1() failed: %m");
+ return log_error_errno(errno, "Failed to create inotify object: %m");
if (inotify_add_watch(m->ask_password_inotify_fd, "/run/systemd/ask-password", IN_CREATE|IN_DELETE|IN_MOVE) < 0) {
- log_error_errno(errno, "Failed to add watch on /run/systemd/ask-password: %m");
+ log_error_errno(errno, "Failed to watch \"/run/systemd/ask-password\": %m");
manager_close_ask_password(m);
return -errno;
}
"MAINPID",
"MANAGERPID",
"NOTIFY_SOCKET",
+ "PIDFILE",
"REMOTE_ADDR",
"REMOTE_PORT",
"SERVICE_RESULT",
return l;
}
-static int manager_default_environment(Manager *m) {
+int manager_default_environment(Manager *m) {
assert(m);
m->transient_environment = strv_free(m->transient_environment);
m->transient_environment = strv_copy(environ);
if (!m->transient_environment)
- return -ENOMEM;
+ return log_oom();
sanitize_environment(m->transient_environment);
}
/* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
- r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, &error, NULL);
+ r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, NULL, &error, NULL);
if (r < 0)
log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r));
}
return 0;
}
-int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, sd_bus_error *e, Job **_ret) {
- int r;
+int manager_add_job(
+ Manager *m,
+ JobType type,
+ Unit *unit,
+ JobMode mode,
+ Set *affected_jobs,
+ sd_bus_error *error,
+ Job **ret) {
+
Transaction *tr;
+ int r;
assert(m);
assert(type < _JOB_TYPE_MAX);
assert(mode < _JOB_MODE_MAX);
if (mode == JOB_ISOLATE && type != JOB_START)
- return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
if (mode == JOB_ISOLATE && !unit->allow_isolate)
- return sd_bus_error_setf(e, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
+ return sd_bus_error_setf(error, BUS_ERROR_NO_ISOLATION, "Operation refused, unit may not be isolated.");
log_unit_debug(unit, "Trying to enqueue job %s/%s/%s", unit->id, job_type_to_string(type), job_mode_to_string(mode));
r = transaction_add_job_and_dependencies(tr, type, unit, NULL, true, false,
IN_SET(mode, JOB_IGNORE_DEPENDENCIES, JOB_IGNORE_REQUIREMENTS),
- mode == JOB_IGNORE_DEPENDENCIES, e);
+ mode == JOB_IGNORE_DEPENDENCIES, error);
if (r < 0)
goto tr_abort;
goto tr_abort;
}
- r = transaction_activate(tr, m, mode, e);
+ r = transaction_activate(tr, m, mode, affected_jobs, error);
if (r < 0)
goto tr_abort;
"Enqueued job %s/%s as %u", unit->id,
job_type_to_string(type), (unsigned) tr->anchor_job->id);
- if (_ret)
- *_ret = tr->anchor_job;
+ if (ret)
+ *ret = tr->anchor_job;
transaction_free(tr);
return 0;
return r;
}
-int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, sd_bus_error *e, Job **ret) {
+int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, sd_bus_error *e, Job **ret) {
Unit *unit = NULL; /* just to appease gcc, initialization is not really necessary */
int r;
return r;
assert(unit);
- return manager_add_job(m, type, unit, mode, e, ret);
+ return manager_add_job(m, type, unit, mode, affected_jobs, e, ret);
}
-int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Job **ret) {
+int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, Job **ret) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(name);
assert(mode < _JOB_MODE_MAX);
- r = manager_add_job_by_name(m, type, name, mode, &error, ret);
+ r = manager_add_job_by_name(m, type, name, mode, affected_jobs, &error, ret);
if (r < 0)
return log_warning_errno(r, "Failed to enqueue %s job for %s: %s", job_mode_to_string(mode), name, bus_error_message(&error, r));
/* Failure in adding individual dependencies is ignored, so this always succeeds. */
transaction_add_propagate_reload_jobs(tr, unit, tr->anchor_job, mode == JOB_IGNORE_DEPENDENCIES, e);
- r = transaction_activate(tr, m, mode, e);
+ r = transaction_activate(tr, m, mode, NULL, e);
if (r < 0)
goto tr_abort;
job_finish_and_invalidate(j, JOB_CANCELED, false, false);
}
+void manager_unwatch_pid(Manager *m, pid_t pid) {
+ assert(m);
+
+ /* First let's drop the unit keyed as "pid". */
+ (void) hashmap_remove(m->watch_pids, PID_TO_PTR(pid));
+
+ /* Then, let's also drop the array keyed by -pid. */
+ free(hashmap_remove(m->watch_pids, PID_TO_PTR(-pid)));
+}
+
static int manager_dispatch_run_queue(sd_event_source *source, void *userdata) {
Manager *m = userdata;
Job *j;
static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
Manager *m = userdata;
- char buf[PATH_MAX+1];
+ char buf[PATH_MAX];
ssize_t n;
n = recv(fd, buf, sizeof(buf), 0);
log_debug("Activating special unit %s", name);
- r = manager_add_job_by_name(m, JOB_START, name, mode, &error, NULL);
+ r = manager_add_job_by_name(m, JOB_START, name, mode, NULL, &error, NULL);
if (r < 0)
log_error("Failed to enqueue %s job: %s", name, bus_error_message(&error, r));
}
if (ratelimit_below(&m->ctrl_alt_del_ratelimit) || m->cad_burst_action == EMERGENCY_ACTION_NONE)
manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE_IRREVERSIBLY);
else
- emergency_action(m, m->cad_burst_action, EMERGENCY_ACTION_WARN, NULL,
+ emergency_action(m, m->cad_burst_action, EMERGENCY_ACTION_WARN, NULL, -1,
"Ctrl-Alt-Del was pressed more than 7 times within 2s");
}
}
if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
- if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED))
+ if (!IN_SET(errno, EAGAIN, ENOENT) && !ERRNO_IS_DISCONNECT(errno))
log_error_errno(errno, "connect() failed: %m");
return;
}
errno = 0;
if (write(fd, message, n + 1) != n + 1)
- if (!IN_SET(errno, EPIPE, EAGAIN, ENOENT, ECONNREFUSED, ECONNRESET, ECONNABORTED))
+ if (!IN_SET(errno, EAGAIN, ENOENT) && !ERRNO_IS_DISCONNECT(errno))
log_error_errno(errno, "Failed to write Plymouth message: %m");
}
}
static int manager_deserialize_units(Manager *m, FILE *f, FDSet *fds) {
- _cleanup_free_ char *line = NULL;
const char *unit_name;
int r;
for (;;) {
+ _cleanup_free_ char *line = NULL;
/* Start marker */
r = read_line(f, LONG_LINE_MAX, &line);
if (r < 0)
return manager_deserialize_units(m, f, fds);
}
-static void manager_flush_finished_jobs(Manager *m) {
- Job *j;
-
- while ((j = set_steal_first(m->pending_finished_jobs))) {
- bus_job_send_removed_signal(j);
- job_free(j);
- }
-
- m->pending_finished_jobs = set_free(m->pending_finished_jobs);
-}
-
int manager_reload(Manager *m) {
_cleanup_(manager_reloading_stopp) Manager *reloading = NULL;
_cleanup_fdset_free_ FDSet *fds = NULL;
manager_ready(m);
- if (!MANAGER_IS_RELOADING(m))
- manager_flush_finished_jobs(m);
-
m->send_reloading_done = true;
return 0;
}
return found;
}
-static const char* system_env_generator_binary_paths[] = {
+static const char *const system_env_generator_binary_paths[] = {
"/run/systemd/system-environment-generators",
"/etc/systemd/system-environment-generators",
"/usr/local/lib/systemd/system-environment-generators",
NULL
};
-static const char* user_env_generator_binary_paths[] = {
+static const char *const user_env_generator_binary_paths[] = {
"/run/systemd/user-environment-generators",
"/etc/systemd/user-environment-generators",
"/usr/local/lib/systemd/user-environment-generators",
static int manager_run_environment_generators(Manager *m) {
char **tmp = NULL; /* this is only used in the forked process, no cleanup here */
- const char **paths;
+ const char *const *paths;
void* args[] = {
[STDOUT_GENERATE] = &tmp,
[STDOUT_COLLECT] = &tmp,
[STDOUT_CONSUME] = &m->transient_environment,
};
+ int r;
if (MANAGER_IS_TEST_RUN(m) && !(m->test_run_flags & MANAGER_TEST_RUN_ENV_GENERATORS))
return 0;
if (!generator_path_any(paths))
return 0;
- return execute_directories(paths, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, m->transient_environment);
+ RUN_WITH_UMASK(0022)
+ r = execute_directories(paths, DEFAULT_TIMEOUT_USEC, gather_environment,
+ args, NULL, m->transient_environment, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
+ return r;
}
static int manager_run_generators(Manager *m) {
argv[4] = NULL;
RUN_WITH_UMASK(0022)
- (void) execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC,
- NULL, NULL, (char**) argv, m->transient_environment);
+ (void) execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC, NULL, NULL,
+ (char**) argv, m->transient_environment, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
r = 0;
a = strv_env_merge(2, m->transient_environment, plus);
if (!a)
- return -ENOMEM;
+ return log_oom();
sanitize_environment(a);
return;
va_start(ap, format);
- status_vprintf(status, true, type == STATUS_TYPE_EPHEMERAL, format, ap);
+ status_vprintf(status, SHOW_STATUS_ELLIPSIZE|(type == STATUS_TYPE_EPHEMERAL ? SHOW_STATUS_EPHEMERAL : 0), format, ap);
va_end(ap);
}