summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/dbus-manager.c10
-rw-r--r--src/core/dbus-timer.c6
-rw-r--r--src/core/dbus-unit.c17
-rw-r--r--src/core/dbus-unit.h2
-rw-r--r--src/core/execute.c4
-rw-r--r--src/core/load-fragment-gperf.gperf.m42
-rw-r--r--src/core/load-fragment.c266
-rw-r--r--src/core/triggers.systemd.in46
8 files changed, 206 insertions, 147 deletions
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 4d730290b2..2562396180 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -630,9 +630,13 @@ static int method_set_unit_properties(sd_bus_message *message, void *userdata, s
if (r < 0)
return r;
- u = manager_get_unit(m, name);
- if (!u)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
+ r = manager_load_unit(m, name, NULL, error, &u);
+ if (r < 0)
+ return r;
+
+ r = bus_unit_check_load_state(u, error);
+ if (r < 0)
+ return r;
return bus_unit_method_set_properties(message, u, error);
}
diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
index 4bee82df07..ec301df6d7 100644
--- a/src/core/dbus-timer.c
+++ b/src/core/dbus-timer.c
@@ -180,7 +180,7 @@ const sd_bus_vtable bus_timer_vtable[] = {
BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("RandomUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -284,7 +284,7 @@ static int bus_timer_set_transient_property(
return 1;
- } else if (streq(name, "RandomUSec")) {
+ } else if (streq(name, "RandomizedDelayUSec")) {
usec_t u = 0;
r = sd_bus_message_read(message, "t", &u);
@@ -295,7 +295,7 @@ static int bus_timer_set_transient_property(
char time[FORMAT_TIMESPAN_MAX];
t->random_usec = u;
- unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomSec=%s\n", format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
+ unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomizedDelaySec=%s\n", format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
}
return 1;
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
index d9b7382c82..66b465a0b7 100644
--- a/src/core/dbus-unit.c
+++ b/src/core/dbus-unit.c
@@ -1251,3 +1251,20 @@ int bus_unit_set_properties(
return n;
}
+
+int bus_unit_check_load_state(Unit *u, sd_bus_error *error) {
+
+ if (u->load_state == UNIT_LOADED)
+ return 0;
+
+ /* Give a better description of the unit error when
+ * possible. Note that in the case of UNIT_MASKED, load_error
+ * is not set. */
+ if (u->load_state == UNIT_MASKED)
+ return sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit is masked.");
+
+ if (u->load_state == UNIT_NOT_FOUND)
+ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit not found.");
+
+ return sd_bus_error_set_errnof(error, u->load_error, "Unit is not loaded properly: %m.");
+}
diff --git a/src/core/dbus-unit.h b/src/core/dbus-unit.h
index b8c6ec398a..ac9ee2d6b8 100644
--- a/src/core/dbus-unit.h
+++ b/src/core/dbus-unit.h
@@ -38,3 +38,5 @@ int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus
int bus_unit_queue_job(sd_bus_message *message, Unit *u, JobType type, JobMode mode, bool reload_if_possible, sd_bus_error *error);
int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitSetPropertiesMode mode, bool commit, sd_bus_error *error);
int bus_unit_method_set_properties(sd_bus_message *message, void *userdata, sd_bus_error *error);
+
+int bus_unit_check_load_state(Unit *u, sd_bus_error *error);
diff --git a/src/core/execute.c b/src/core/execute.c
index 07979bf8b3..677480cbe1 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -2414,8 +2414,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
for (i = 0; i < RLIM_NLIMITS; i++)
if (c->rlimit[i])
- fprintf(f, "%s%s: "RLIM_FMT"\n",
- prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max);
+ fprintf(f, "%s%s: " RLIM_FMT " " RLIM_FMT "\n",
+ prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur, c->rlimit[i]->rlim_max);
if (c->ioprio_set) {
_cleanup_free_ char *class_str = NULL;
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index c64850802e..0408b9a829 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -347,7 +347,7 @@ Timer.Persistent, config_parse_bool, 0,
Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system)
Timer.RemainAfterElapse, config_parse_bool, 0, offsetof(Timer, remain_after_elapse)
Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec)
-Timer.RandomSec, config_parse_sec, 0, offsetof(Timer, random_usec)
+Timer.RandomizedDelaySec, config_parse_sec, 0, offsetof(Timer, random_usec)
Timer.Unit, config_parse_trigger_unit, 0, 0
m4_dnl
Path.PathExists, config_parse_path_spec, 0, 0
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index d5cf476fda..3c124495b6 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -1089,59 +1089,123 @@ int config_parse_bounding_set(
return 0;
}
-int config_parse_limit(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+static int rlim_parse_u64(const char *val, rlim_t *res) {
+ int r = 0;
- struct rlimit **rl = data;
- rlim_t v;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- rl += ltype;
-
- if (streq(rvalue, "infinity"))
- v = RLIM_INFINITY;
+ if (streq(val, "infinity"))
+ *res = RLIM_INFINITY;
else {
uint64_t u;
/* setrlimit(2) suggests rlim_t is always 64bit on Linux. */
assert_cc(sizeof(rlim_t) == sizeof(uint64_t));
- r = safe_atou64(rvalue, &u);
+ r = safe_atou64(val, &u);
if (r >= 0 && u >= (uint64_t) RLIM_INFINITY)
r = -ERANGE;
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
- return 0;
- }
+ if (r == 0)
+ *res = (rlim_t) u;
+ }
+ return r;
+}
- v = (rlim_t) u;
+static int rlim_parse_size(const char *val, rlim_t *res) {
+ int r = 0;
+
+ if (streq(val, "infinity"))
+ *res = RLIM_INFINITY;
+ else {
+ uint64_t u;
+
+ r = parse_size(val, 1024, &u);
+ if (r >= 0 && u >= (uint64_t) RLIM_INFINITY)
+ r = -ERANGE;
+ if (r == 0)
+ *res = (rlim_t) u;
}
+ return r;
+}
+
+static int rlim_parse_sec(const char *val, rlim_t *res) {
+ int r = 0;
+
+ if (streq(val, "infinity"))
+ *res = RLIM_INFINITY;
+ else {
+ usec_t t;
+
+ r = parse_sec(val, &t);
+ if (r < 0)
+ return r;
+ if (t == USEC_INFINITY)
+ *res = RLIM_INFINITY;
+ else
+ *res = (rlim_t) (DIV_ROUND_UP(t, USEC_PER_SEC));
+
+ }
+ return r;
+}
+
+static int rlim_parse_usec(const char *val, rlim_t *res) {
+ int r = 0;
+
+ if (streq(val, "infinity"))
+ *res = RLIM_INFINITY;
+ else {
+ usec_t t;
+
+ r = parse_time(val, &t, 1);
+ if (r < 0)
+ return r;
+ if (t == USEC_INFINITY)
+ *res = RLIM_INFINITY;
+ else
+ *res = (rlim_t) t;
+ }
+ return r;
+}
+
+static int parse_rlimit_range(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *value,
+ struct rlimit **rl,
+ int (*rlim_parser)(const char *, rlim_t *)) {
+
+ const char *whole_value = value;
+ rlim_t soft, hard;
+ _cleanup_free_ char *sword = NULL, *hword = NULL;
+ int nwords, r;
+
+ assert(value);
+
+ /* <value> or <soft:hard> */
+ nwords = extract_many_words(&value, ":", EXTRACT_DONT_COALESCE_SEPARATORS, &sword, &hword, NULL);
+ r = nwords < 0 ? nwords : nwords == 0 ? -EINVAL : 0;
+
+ if (r == 0)
+ r = rlim_parser(sword, &soft);
+ if (r == 0 && nwords == 2)
+ r = rlim_parser(hword, &hard);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", whole_value);
+ return 0;
+ }
+ if (nwords == 2 && soft > hard)
+ return log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid resource value ("RLIM_FMT" > "RLIM_FMT"), ignoring: %s", soft, hard, whole_value);
if (!*rl) {
*rl = new(struct rlimit, 1);
if (!*rl)
return log_oom();
}
-
- (*rl)->rlim_cur = (*rl)->rlim_max = v;
+ (*rl)->rlim_cur = soft;
+ (*rl)->rlim_max = nwords == 2 ? hard : soft;
return 0;
}
-int config_parse_bytes_limit(
+int config_parse_limit(
const char *unit,
const char *filename,
unsigned line,
@@ -1154,8 +1218,6 @@ int config_parse_bytes_limit(
void *userdata) {
struct rlimit **rl = data;
- rlim_t bytes;
- int r;
assert(filename);
assert(lvalue);
@@ -1163,31 +1225,30 @@ int config_parse_bytes_limit(
assert(data);
rl += ltype;
+ return parse_rlimit_range(unit, filename, line, rvalue, rl, rlim_parse_u64);
+}
- if (streq(rvalue, "infinity"))
- bytes = RLIM_INFINITY;
- else {
- uint64_t u;
-
- r = parse_size(rvalue, 1024, &u);
- if (r >= 0 && u >= (uint64_t) RLIM_INFINITY)
- r = -ERANGE;
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
- return 0;
- }
+int config_parse_bytes_limit(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
- bytes = (rlim_t) u;
- }
+ struct rlimit **rl = data;
- if (!*rl) {
- *rl = new(struct rlimit, 1);
- if (!*rl)
- return log_oom();
- }
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
- (*rl)->rlim_cur = (*rl)->rlim_max = bytes;
- return 0;
+ rl += ltype;
+ return parse_rlimit_range(unit, filename, line, rvalue, rl, rlim_parse_size);
}
int config_parse_sec_limit(
@@ -1203,8 +1264,6 @@ int config_parse_sec_limit(
void *userdata) {
struct rlimit **rl = data;
- rlim_t seconds;
- int r;
assert(filename);
assert(lvalue);
@@ -1212,35 +1271,9 @@ int config_parse_sec_limit(
assert(data);
rl += ltype;
-
- if (streq(rvalue, "infinity"))
- seconds = RLIM_INFINITY;
- else {
- usec_t t;
-
- r = parse_sec(rvalue, &t);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
- return 0;
- }
-
- if (t == USEC_INFINITY)
- seconds = RLIM_INFINITY;
- else
- seconds = (rlim_t) (DIV_ROUND_UP(t, USEC_PER_SEC));
- }
-
- if (!*rl) {
- *rl = new(struct rlimit, 1);
- if (!*rl)
- return log_oom();
- }
-
- (*rl)->rlim_cur = (*rl)->rlim_max = seconds;
- return 0;
+ return parse_rlimit_range(unit, filename, line, rvalue, rl, rlim_parse_sec);
}
-
int config_parse_usec_limit(
const char *unit,
const char *filename,
@@ -1254,8 +1287,6 @@ int config_parse_usec_limit(
void *userdata) {
struct rlimit **rl = data;
- rlim_t useconds;
- int r;
assert(filename);
assert(lvalue);
@@ -1263,33 +1294,10 @@ int config_parse_usec_limit(
assert(data);
rl += ltype;
+ return parse_rlimit_range(unit, filename, line, rvalue, rl, rlim_parse_usec);
+}
- if (streq(rvalue, "infinity"))
- useconds = RLIM_INFINITY;
- else {
- usec_t t;
-
- r = parse_time(rvalue, &t, 1);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue);
- return 0;
- }
-
- if (t == USEC_INFINITY)
- useconds = RLIM_INFINITY;
- else
- useconds = (rlim_t) t;
- }
-
- if (!*rl) {
- *rl = new(struct rlimit, 1);
- if (!*rl)
- return log_oom();
- }
- (*rl)->rlim_cur = (*rl)->rlim_max = useconds;
- return 0;
-}
#ifdef HAVE_SYSV_COMPAT
int config_parse_sysv_priority(const char *unit,
@@ -1336,38 +1344,28 @@ int config_parse_exec_mount_flags(const char *unit,
void *data,
void *userdata) {
- ExecContext *c = data;
- const char *word, *state;
- size_t l;
+
unsigned long flags = 0;
+ ExecContext *c = data;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
- FOREACH_WORD_SEPARATOR(word, l, rvalue, ", ", state) {
- _cleanup_free_ char *t;
-
- t = strndup(word, l);
- if (!t)
- return log_oom();
-
- if (streq(t, "shared"))
- flags = MS_SHARED;
- else if (streq(t, "slave"))
- flags = MS_SLAVE;
- else if (streq(t, "private"))
- flags = MS_PRIVATE;
- else {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring: %s", t, rvalue);
- return 0;
- }
+ if (streq(rvalue, "shared"))
+ flags = MS_SHARED;
+ else if (streq(rvalue, "slave"))
+ flags = MS_SLAVE;
+ else if (streq(rvalue, "private"))
+ flags = MS_PRIVATE;
+ else {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring.", rvalue);
+ return 0;
}
- if (!isempty(state))
- log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
c->mount_flags = flags;
+
return 0;
}
diff --git a/src/core/triggers.systemd.in b/src/core/triggers.systemd.in
index 141f42dbcf..9e18a39a67 100644
--- a/src/core/triggers.systemd.in
+++ b/src/core/triggers.systemd.in
@@ -19,8 +19,46 @@
# The contents of this are an example to be copied into systemd.spec.
-%transfiletriggerin -- @systemunitdir@ /etc/systemd/system
-systemctl daemon-reload &>/dev/null || :
+%transfiletriggerin -P 900900 -p <lua> -- @systemunitdir@ /etc/systemd/system
+-- This script will run after any package is initially installed or
+-- upgraded. We care about the case where a package is initially
+-- installed, because other cases are covered by the *un scriptlets,
+-- so sometimes we will reload needlessly.
-%transfiletriggerun -- @systemunitdir@ /etc/systemd/system
-systemctl daemon-reload &>/dev/null || :
+pid = posix.fork()
+if pid == 0 then
+ assert(posix.exec("%{_bindir}/systemctl", "daemon-reload"))
+elseif pid > 0 then
+ posix.wait(pid)
+end
+
+%transfiletriggerun -p <lua> -- @systemunitdir@ /etc/systemd/system
+-- On removal, we need to run daemon-reload after any units have been
+-- removed. %transfiletriggerpostun would be ideal, but it does not get
+-- executed for some reason.
+-- On upgrade, we need to run daemon-reload after any new unit files
+-- have been installed, but before %postun scripts in packages get
+-- executed. %transfiletriggerun gets the right list of files
+-- but it is invoked too early (before changes happen).
+-- %filetriggerpostun happens at the right time, but it fires for
+-- every package.
+-- To execute the reload at the right time, we create a state
+-- file in %transfiletriggerun and execute the daemon-reload in
+-- the first %filetriggerpostun.
+
+posix.mkdir("%{_localstatedir}/lib")
+posix.mkdir("%{_localstatedir}/lib/rpm-state")
+posix.mkdir("%{_localstatedir}/lib/rpm-state/systemd")
+io.open("%{_localstatedir}/lib/rpm-state/systemd/needs-reload", "w")
+
+%filetriggerpostun -P 1000100 -p <lua> -- @systemunitdir@ /etc/systemd/system
+if posix.access("%{_localstatedir}/lib/rpm-state/systemd/needs-reload") then
+ posix.unlink("%{_localstatedir}/lib/rpm-state/systemd/needs-reload")
+ posix.rmdir("%{_localstatedir}/lib/rpm-state/systemd")
+ pid = posix.fork()
+ if pid == 0 then
+ assert(posix.exec("%{_bindir}/systemctl", "daemon-reload"))
+ elseif pid > 0 then
+ posix.wait(pid)
+ end
+end