Add the FileDescriptorStorePreserve= option to the service
This commit is contained in:
parent
808da02699
commit
995e1ad82b
310
backport-Add-implicit-sentinel-to-strv_env_merge.patch
Normal file
310
backport-Add-implicit-sentinel-to-strv_env_merge.patch
Normal file
@ -0,0 +1,310 @@
|
||||
From 4ab3d29ff03c0508f47846875d9310cbc5b8cd0f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Sat, 7 Aug 2021 10:16:19 +0200
|
||||
Subject: [PATCH] Add implicit sentinel to strv_env_merge()
|
||||
|
||||
Just to make it a tiny bit nicer to use.
|
||||
|
||||
---
|
||||
src/basic/env-util.c | 40 ++++++++++++++++++++++++++--------------
|
||||
src/basic/env-util.h | 3 ++-
|
||||
src/core/dbus-execute.c | 4 ++--
|
||||
src/core/execute.c | 5 ++---
|
||||
src/core/locale-setup.c | 2 +-
|
||||
src/core/manager.c | 6 +++---
|
||||
src/core/service.c | 2 +-
|
||||
src/notify/notify.c | 2 +-
|
||||
src/nspawn/nspawn.c | 20 ++++++++++----------
|
||||
src/run/run.c | 2 +-
|
||||
src/test/test-env-util.c | 2 +-
|
||||
11 files changed, 50 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/src/basic/env-util.c b/src/basic/env-util.c
|
||||
index 81b1e3f10e..0c30ddc277 100644
|
||||
--- a/src/basic/env-util.c
|
||||
+++ b/src/basic/env-util.c
|
||||
@@ -183,39 +183,51 @@ static int env_append(char **r, char ***k, char **a) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-char **strv_env_merge(size_t n_lists, ...) {
|
||||
- _cleanup_strv_free_ char **ret = NULL;
|
||||
- size_t n = 0;
|
||||
- char **l, **k;
|
||||
+char** _strv_env_merge(char **first, ...) {
|
||||
+ _cleanup_strv_free_ char **merged = NULL;
|
||||
+ char **k;
|
||||
va_list ap;
|
||||
|
||||
/* Merges an arbitrary number of environment sets */
|
||||
|
||||
- va_start(ap, n_lists);
|
||||
- for (size_t i = 0; i < n_lists; i++) {
|
||||
+ size_t n = strv_length(first);
|
||||
+
|
||||
+ va_start(ap, first);
|
||||
+ for (;;) {
|
||||
+ char **l;
|
||||
+
|
||||
l = va_arg(ap, char**);
|
||||
+ if (l == POINTER_MAX)
|
||||
+ break;
|
||||
+
|
||||
n += strv_length(l);
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
- ret = new(char*, n+1);
|
||||
- if (!ret)
|
||||
+ k = merged = new(char*, n + 1);
|
||||
+ if (!merged)
|
||||
return NULL;
|
||||
+ merged[0] = NULL;
|
||||
|
||||
- *ret = NULL;
|
||||
- k = ret;
|
||||
+ if (env_append(merged, &k, first) < 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ va_start(ap, first);
|
||||
+ for (;;) {
|
||||
+ char **l;
|
||||
|
||||
- va_start(ap, n_lists);
|
||||
- for (size_t i = 0; i < n_lists; i++) {
|
||||
l = va_arg(ap, char**);
|
||||
- if (env_append(ret, &k, l) < 0) {
|
||||
+ if (l == POINTER_MAX)
|
||||
+ break;
|
||||
+
|
||||
+ if (env_append(merged, &k, l) < 0) {
|
||||
va_end(ap);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
- return TAKE_PTR(ret);
|
||||
+ return TAKE_PTR(merged);
|
||||
}
|
||||
|
||||
static bool env_match(const char *t, const char *pattern) {
|
||||
diff --git a/src/basic/env-util.h b/src/basic/env-util.h
|
||||
index 1fbe7e4270..18d10ebab8 100644
|
||||
--- a/src/basic/env-util.h
|
||||
+++ b/src/basic/env-util.h
|
||||
@@ -39,7 +39,8 @@ char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const cha
|
||||
bool strv_env_name_is_valid(char **l);
|
||||
bool strv_env_name_or_assignment_is_valid(char **l);
|
||||
|
||||
-char **strv_env_merge(size_t n_lists, ...);
|
||||
+char** _strv_env_merge(char **first, ...);
|
||||
+#define strv_env_merge(first, ...) _strv_env_merge(first, __VA_ARGS__, POINTER_MAX)
|
||||
char **strv_env_delete(char **x, size_t n_lists, ...); /* New copy */
|
||||
|
||||
char **strv_env_unset(char **l, const char *p); /* In place ... */
|
||||
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
|
||||
index f6783e924a..5ea97b9194 100644
|
||||
--- a/src/core/dbus-execute.c
|
||||
+++ b/src/core/dbus-execute.c
|
||||
@@ -2888,7 +2888,7 @@ int bus_exec_context_set_transient_property(
|
||||
if (!joined)
|
||||
return -ENOMEM;
|
||||
|
||||
- e = strv_env_merge(2, c->environment, l);
|
||||
+ e = strv_env_merge(c->environment, l);
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -2922,7 +2922,7 @@ int bus_exec_context_set_transient_property(
|
||||
if (!joined)
|
||||
return -ENOMEM;
|
||||
|
||||
- e = strv_env_merge(2, c->unset_environment, l);
|
||||
+ e = strv_env_merge(c->unset_environment, l);
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
|
||||
diff --git a/src/core/execute.c b/src/core/execute.c
|
||||
index 4608956259..5bee44ac7b 100644
|
||||
--- a/src/core/execute.c
|
||||
+++ b/src/core/execute.c
|
||||
@@ -4158,8 +4158,7 @@ static int exec_child(
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
- accum_env = strv_env_merge(5,
|
||||
- params->environment,
|
||||
+ accum_env = strv_env_merge(params->environment,
|
||||
our_env,
|
||||
pass_env,
|
||||
context->environment,
|
||||
@@ -5214,7 +5213,7 @@ static int exec_context_load_environment(const Unit *unit, const ExecContext *c,
|
||||
else {
|
||||
char **m;
|
||||
|
||||
- m = strv_env_merge(2, r, p);
|
||||
+ m = strv_env_merge(r, p);
|
||||
strv_free(r);
|
||||
strv_free(p);
|
||||
if (!m)
|
||||
diff --git a/src/core/locale-setup.c b/src/core/locale-setup.c
|
||||
index 64761ddb11..59ddb9c487 100644
|
||||
--- a/src/core/locale-setup.c
|
||||
+++ b/src/core/locale-setup.c
|
||||
@@ -85,7 +85,7 @@ int locale_setup(char ***environment) {
|
||||
else {
|
||||
char **merged;
|
||||
|
||||
- merged = strv_env_merge(2, *environment, add);
|
||||
+ merged = strv_env_merge(*environment, add);
|
||||
if (!merged)
|
||||
return -ENOMEM;
|
||||
|
||||
diff --git a/src/core/manager.c b/src/core/manager.c
|
||||
index 24dfe9fc06..d76b7b2b16 100644
|
||||
--- a/src/core/manager.c
|
||||
+++ b/src/core/manager.c
|
||||
@@ -3672,7 +3672,7 @@ int manager_transient_environment_add(Manager *m, char **plus) {
|
||||
if (strv_isempty(plus))
|
||||
return 0;
|
||||
|
||||
- a = strv_env_merge(2, m->transient_environment, plus);
|
||||
+ a = strv_env_merge(m->transient_environment, plus);
|
||||
if (!a)
|
||||
return log_oom();
|
||||
|
||||
@@ -3704,7 +3704,7 @@ int manager_client_environment_modify(
|
||||
}
|
||||
|
||||
if (!strv_isempty(plus)) {
|
||||
- b = strv_env_merge(2, l, plus);
|
||||
+ b = strv_env_merge(l, plus);
|
||||
if (!b) {
|
||||
strv_free(a);
|
||||
return -ENOMEM;
|
||||
@@ -3731,7 +3731,7 @@ int manager_get_effective_environment(Manager *m, char ***ret) {
|
||||
assert(m);
|
||||
assert(ret);
|
||||
|
||||
- l = strv_env_merge(2, m->transient_environment, m->client_environment);
|
||||
+ l = strv_env_merge(m->transient_environment, m->client_environment);
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index ddcfeb8523..4115db0a30 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -1546,7 +1546,7 @@ static int service_spawn(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- final_env = strv_env_merge(2, exec_params.environment, our_env, NULL);
|
||||
+ final_env = strv_env_merge(exec_params.environment, our_env);
|
||||
if (!final_env)
|
||||
return -ENOMEM;
|
||||
|
||||
diff --git a/src/notify/notify.c b/src/notify/notify.c
|
||||
index 49d5f3ec92..b468a5bc44 100644
|
||||
--- a/src/notify/notify.c
|
||||
+++ b/src/notify/notify.c
|
||||
@@ -232,7 +232,7 @@ static int run(int argc, char* argv[]) {
|
||||
|
||||
our_env[i++] = NULL;
|
||||
|
||||
- final_env = strv_env_merge(2, our_env, argv + optind);
|
||||
+ final_env = strv_env_merge(our_env, argv + optind);
|
||||
if (!final_env)
|
||||
return log_oom();
|
||||
|
||||
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
|
||||
index d75cce408e..cf89b27dfa 100644
|
||||
--- a/src/nspawn/nspawn.c
|
||||
+++ b/src/nspawn/nspawn.c
|
||||
@@ -3189,8 +3189,8 @@ static int inner_child(
|
||||
_cleanup_free_ char *home = NULL;
|
||||
char as_uuid[ID128_UUID_STRING_MAX];
|
||||
size_t n_env = 1;
|
||||
- const char *envp[] = {
|
||||
- "PATH=" DEFAULT_PATH_COMPAT,
|
||||
+ char *envp[] = {
|
||||
+ (char*) "PATH=" DEFAULT_PATH_COMPAT,
|
||||
NULL, /* container */
|
||||
NULL, /* TERM */
|
||||
NULL, /* HOME */
|
||||
@@ -3426,17 +3426,17 @@ static int inner_child(
|
||||
n_env++;
|
||||
|
||||
if (home || !uid_is_valid(arg_uid) || arg_uid == 0)
|
||||
- if (asprintf((char**)(envp + n_env++), "HOME=%s", home ?: "/root") < 0)
|
||||
+ if (asprintf(envp + n_env++, "HOME=%s", home ?: "/root") < 0)
|
||||
return log_oom();
|
||||
|
||||
if (arg_user || !uid_is_valid(arg_uid) || arg_uid == 0)
|
||||
- if (asprintf((char**)(envp + n_env++), "USER=%s", arg_user ?: "root") < 0 ||
|
||||
- asprintf((char**)(envp + n_env++), "LOGNAME=%s", arg_user ? arg_user : "root") < 0)
|
||||
+ if (asprintf(envp + n_env++, "USER=%s", arg_user ?: "root") < 0 ||
|
||||
+ asprintf(envp + n_env++, "LOGNAME=%s", arg_user ? arg_user : "root") < 0)
|
||||
return log_oom();
|
||||
|
||||
assert(!sd_id128_is_null(arg_uuid));
|
||||
|
||||
- if (asprintf((char**)(envp + n_env++), "container_uuid=%s", id128_to_uuid_string(arg_uuid, as_uuid)) < 0)
|
||||
+ if (asprintf(envp + n_env++, "container_uuid=%s", id128_to_uuid_string(arg_uuid, as_uuid)) < 0)
|
||||
return log_oom();
|
||||
|
||||
if (fdset_size(fds) > 0) {
|
||||
@@ -3444,11 +3444,11 @@ static int inner_child(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to unset O_CLOEXEC for file descriptors.");
|
||||
|
||||
- if ((asprintf((char **)(envp + n_env++), "LISTEN_FDS=%u", fdset_size(fds)) < 0) ||
|
||||
- (asprintf((char **)(envp + n_env++), "LISTEN_PID=1") < 0))
|
||||
+ if ((asprintf(envp + n_env++, "LISTEN_FDS=%u", fdset_size(fds)) < 0) ||
|
||||
+ (asprintf(envp + n_env++, "LISTEN_PID=1") < 0))
|
||||
return log_oom();
|
||||
}
|
||||
- if (asprintf((char **)(envp + n_env++), "NOTIFY_SOCKET=%s", NSPAWN_NOTIFY_SOCKET_PATH) < 0)
|
||||
+ if (asprintf(envp + n_env++, "NOTIFY_SOCKET=%s", NSPAWN_NOTIFY_SOCKET_PATH) < 0)
|
||||
return log_oom();
|
||||
|
||||
if (arg_n_credentials > 0) {
|
||||
@@ -3458,7 +3458,7 @@ static int inner_child(
|
||||
n_env++;
|
||||
}
|
||||
|
||||
- env_use = strv_env_merge(3, envp, os_release_pairs, arg_setenv);
|
||||
+ env_use = strv_env_merge(envp, os_release_pairs, arg_setenv);
|
||||
if (!env_use)
|
||||
return log_oom();
|
||||
|
||||
diff --git a/src/run/run.c b/src/run/run.c
|
||||
index 0be974f03a..993f1bc4f4 100644
|
||||
--- a/src/run/run.c
|
||||
+++ b/src/run/run.c
|
||||
@@ -1526,7 +1526,7 @@ static int start_transient_scope(sd_bus *bus) {
|
||||
return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
|
||||
}
|
||||
|
||||
- env = strv_env_merge(3, environ, user_env, arg_environment);
|
||||
+ env = strv_env_merge(environ, user_env, arg_environment);
|
||||
if (!env)
|
||||
return log_oom();
|
||||
|
||||
diff --git a/src/test/test-env-util.c b/src/test/test-env-util.c
|
||||
index ed4580e4af..5bf130ed86 100644
|
||||
--- a/src/test/test-env-util.c
|
||||
+++ b/src/test/test-env-util.c
|
||||
@@ -81,7 +81,7 @@ static void test_strv_env_merge(void) {
|
||||
b = strv_new("FOO=KKK", "FOO=", "PIEP=", "SCHLUMPF=SMURFF", "NANANANA=YES");
|
||||
assert_se(b);
|
||||
|
||||
- r = strv_env_merge(2, a, b);
|
||||
+ r = strv_env_merge(a, b);
|
||||
assert_se(r);
|
||||
assert_se(streq(r[0], "FOO="));
|
||||
assert_se(streq(r[1], "WALDO="));
|
||||
--
|
||||
2.33.0
|
||||
|
||||
166
backport-TEST-80-synchronize-explicitly-instead-of-by-time.patch
Normal file
166
backport-TEST-80-synchronize-explicitly-instead-of-by-time.patch
Normal file
@ -0,0 +1,166 @@
|
||||
From 09ba6d1a14ba027f2bc4e3426c7dd85db19e720e Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 28 Mar 2023 16:35:35 +0200
|
||||
Subject: [PATCH] TEST-80: synchronize explicitly instead of by time
|
||||
|
||||
This removes "sleep" invocations, and makes the notify access testcase a
|
||||
lot more robust to runtime jitter. We use a pair of fifos in the fs to
|
||||
sync instead.
|
||||
|
||||
Also various other improvoements, including comments.
|
||||
|
||||
(Also removes the unnecessary "no-qemu" restriction)
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd/commit/09ba6d1a14ba027f2bc4e3426c7dd85db19e720e
|
||||
|
||||
---
|
||||
test/TEST-80-NOTIFYACCESS/test.sh | 1 -
|
||||
test/testsuite-80.units/test.sh | 59 +++++++++++++++++++++++++------
|
||||
test/units/testsuite-80.sh | 30 +++++++++++++---
|
||||
3 files changed, 73 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/test/TEST-80-NOTIFYACCESS/test.sh b/test/TEST-80-NOTIFYACCESS/test.sh
|
||||
index b4d2452b75..8ec5b1bc5f 100755
|
||||
--- a/test/TEST-80-NOTIFYACCESS/test.sh
|
||||
+++ b/test/TEST-80-NOTIFYACCESS/test.sh
|
||||
@@ -3,7 +3,6 @@
|
||||
set -e
|
||||
|
||||
TEST_DESCRIPTION="test NotifyAccess through sd-notify"
|
||||
-TEST_NO_QEMU=1
|
||||
|
||||
# shellcheck source=test/test-functions
|
||||
. "${TEST_BASE_DIR:?}/test-functions"
|
||||
diff --git a/test/testsuite-80.units/test.sh b/test/testsuite-80.units/test.sh
|
||||
index 3ca71d5648..565ed8d35a 100755
|
||||
--- a/test/testsuite-80.units/test.sh
|
||||
+++ b/test/testsuite-80.units/test.sh
|
||||
@@ -4,23 +4,60 @@
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
-systemd-notify --status="Test starts, waiting for 5 seconds"
|
||||
-sleep 5
|
||||
+sync_in() {
|
||||
+ read -r x < /tmp/syncfifo2
|
||||
+ test "$x" = "$1"
|
||||
+}
|
||||
|
||||
+sync_out() {
|
||||
+ echo "$1" > /tmp/syncfifo1
|
||||
+}
|
||||
+
|
||||
+export SYSTEMD_LOG_LEVEL=debug
|
||||
+
|
||||
+echo "toplevel PID: $BASHPID"
|
||||
+
|
||||
+systemd-notify --status="Test starts"
|
||||
+sync_out a
|
||||
+sync_in b
|
||||
(
|
||||
- systemd-notify --pid=auto
|
||||
+ echo "subshell PID: $BASHPID"
|
||||
+
|
||||
+ # Make us main process
|
||||
+ systemd-notify --pid="$BASHPID"
|
||||
+
|
||||
+ # Lock down access to just us
|
||||
systemd-notify "NOTIFYACCESS=main"
|
||||
|
||||
- systemd-notify --status="Sending READY=1 in an unpriviledged process"
|
||||
- (
|
||||
- sleep 0.1
|
||||
- systemd-notify --ready
|
||||
- )
|
||||
- sleep 10
|
||||
+ # This should still work
|
||||
+ systemd-notify --status="Sending READY=1 in an unprivileged process"
|
||||
+
|
||||
+ # Send as subprocess of the subshell, this should not work
|
||||
+ systemd-notify --ready --pid=self --status "BOGUS1"
|
||||
|
||||
- systemd-notify "MAINPID=$$"
|
||||
+ sync_out c
|
||||
+ sync_in d
|
||||
+
|
||||
+ # Move main process back to toplevel
|
||||
+ systemd-notify --pid=parent "MAINPID=$$"
|
||||
+
|
||||
+ # Should be dropped again
|
||||
+ systemd-notify --status="BOGUS2" --pid=parent
|
||||
+
|
||||
+ # Apparently, bash will automatically invoke the last command in a subshell
|
||||
+ # via a simple execve() rather than fork()ing first. But we want that the
|
||||
+ # previous command uses the subshell's PID, hence let's insert a final,
|
||||
+ # bogus redundant command as last command to run in the subshell, so that
|
||||
+ # bash can't optimize things like that.
|
||||
+ echo "bye"
|
||||
)
|
||||
|
||||
+echo "toplevel again: $BASHPID"
|
||||
+
|
||||
systemd-notify --ready --status="OK"
|
||||
systemd-notify "NOTIFYACCESS=none"
|
||||
-sleep infinity
|
||||
+systemd-notify --status="BOGUS3"
|
||||
+
|
||||
+sync_out e
|
||||
+
|
||||
+exec sleep infinity
|
||||
diff --git a/test/units/testsuite-80.sh b/test/units/testsuite-80.sh
|
||||
index 5f57569b07..43647a707f 100755
|
||||
--- a/test/units/testsuite-80.sh
|
||||
+++ b/test/units/testsuite-80.sh
|
||||
@@ -9,17 +9,35 @@ set -o pipefail
|
||||
|
||||
: >/failed
|
||||
|
||||
+mkfifo /tmp/syncfifo1 /tmp/syncfifo2
|
||||
+
|
||||
+sync_in() {
|
||||
+ read -r x < /tmp/syncfifo1
|
||||
+ test "$x" = "$1"
|
||||
+}
|
||||
+
|
||||
+sync_out() {
|
||||
+ echo "$1" > /tmp/syncfifo2
|
||||
+}
|
||||
+
|
||||
+export SYSTEMD_LOG_LEVEL=debug
|
||||
+
|
||||
systemctl --no-block start notify.service
|
||||
-sleep 2
|
||||
|
||||
-assert_eq "$(systemctl show notify.service -p StatusText --value)" "Test starts, waiting for 5 seconds"
|
||||
+sync_in a
|
||||
+
|
||||
assert_eq "$(systemctl show notify.service -p NotifyAccess --value)" "all"
|
||||
-sleep 5
|
||||
+assert_eq "$(systemctl show notify.service -p StatusText --value)" "Test starts"
|
||||
+
|
||||
+sync_out b
|
||||
+sync_in c
|
||||
|
||||
assert_eq "$(systemctl show notify.service -p NotifyAccess --value)" "main"
|
||||
-assert_eq "$(systemctl show notify.service -p StatusText --value)" "Sending READY=1 in an unpriviledged process"
|
||||
+assert_eq "$(systemctl show notify.service -p StatusText --value)" "Sending READY=1 in an unprivileged process"
|
||||
assert_rc 3 systemctl --quiet is-active notify.service
|
||||
-sleep 10
|
||||
+
|
||||
+sync_out d
|
||||
+sync_in e
|
||||
|
||||
systemctl --quiet is-active notify.service
|
||||
assert_eq "$(systemctl show notify.service -p StatusText --value)" "OK"
|
||||
@@ -28,5 +46,7 @@ assert_eq "$(systemctl show notify.service -p NotifyAccess --value)" "none"
|
||||
systemctl stop notify.service
|
||||
assert_eq "$(systemctl show notify.service -p NotifyAccess --value)" "all"
|
||||
|
||||
+rm /tmp/syncfifo1 /tmp/syncfifo2
|
||||
+
|
||||
touch /testok
|
||||
rm /failed
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,453 @@
|
||||
From 14337c374a641badf55cf9ce6ec1fb387886b651 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
Date: Fri, 26 Nov 2021 09:47:44 +0100
|
||||
Subject: [PATCH] basic/strv: inline variables and modernize style a bit
|
||||
|
||||
Conflict:Context Adaptation.
|
||||
Reference:https://github.com/systemd/systemd/commit/14337c374a641badf55cf9ce6ec1fb387886b651
|
||||
|
||||
---
|
||||
src/basic/strv.c | 82 +++++++++++++++++++++---------------------------
|
||||
src/basic/strv.h | 42 ++++++++++++-------------
|
||||
2 files changed, 56 insertions(+), 68 deletions(-)
|
||||
|
||||
diff --git a/src/basic/strv.c b/src/basic/strv.c
|
||||
index 3adf3c5..e10af33 100644
|
||||
--- a/src/basic/strv.c
|
||||
+++ b/src/basic/strv.c
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
-char *strv_find(char * const *l, const char *name) {
|
||||
+char* strv_find(char * const *l, const char *name) {
|
||||
char * const *i;
|
||||
|
||||
assert(name);
|
||||
@@ -28,7 +28,7 @@ char *strv_find(char * const *l, const char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-char *strv_find_case(char * const *l, const char *name) {
|
||||
+char* strv_find_case(char * const *l, const char *name) {
|
||||
char * const *i;
|
||||
|
||||
assert(name);
|
||||
@@ -40,7 +40,7 @@ char *strv_find_case(char * const *l, const char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-char *strv_find_prefix(char * const *l, const char *name) {
|
||||
+char* strv_find_prefix(char * const *l, const char *name) {
|
||||
char * const *i;
|
||||
|
||||
assert(name);
|
||||
@@ -52,7 +52,7 @@ char *strv_find_prefix(char * const *l, const char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-char *strv_find_startswith(char * const *l, const char *name) {
|
||||
+char* strv_find_startswith(char * const *l, const char *name) {
|
||||
char * const *i, *e;
|
||||
|
||||
assert(name);
|
||||
@@ -69,19 +69,17 @@ char *strv_find_startswith(char * const *l, const char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-char **strv_free(char **l) {
|
||||
- char **k;
|
||||
-
|
||||
+char** strv_free(char **l) {
|
||||
if (!l)
|
||||
return NULL;
|
||||
|
||||
- for (k = l; *k; k++)
|
||||
+ for (char **k = l; *k; k++)
|
||||
free(*k);
|
||||
|
||||
return mfree(l);
|
||||
}
|
||||
|
||||
-char **strv_free_erase(char **l) {
|
||||
+char** strv_free_erase(char **l) {
|
||||
char **i;
|
||||
|
||||
STRV_FOREACH(i, l)
|
||||
@@ -90,7 +88,7 @@ char **strv_free_erase(char **l) {
|
||||
return mfree(l);
|
||||
}
|
||||
|
||||
-char **strv_copy(char * const *l) {
|
||||
+char** strv_copy(char * const *l) {
|
||||
char **r, **k;
|
||||
|
||||
k = r = new(char*, strv_length(l) + 1);
|
||||
@@ -122,7 +120,7 @@ size_t strv_length(char * const *l) {
|
||||
return n;
|
||||
}
|
||||
|
||||
-char **strv_new_ap(const char *x, va_list ap) {
|
||||
+char** strv_new_ap(const char *x, va_list ap) {
|
||||
_cleanup_strv_free_ char **a = NULL;
|
||||
size_t n = 0, i = 0;
|
||||
va_list aq;
|
||||
@@ -161,7 +159,7 @@ char **strv_new_ap(const char *x, va_list ap) {
|
||||
return TAKE_PTR(a);
|
||||
}
|
||||
|
||||
-char **strv_new_internal(const char *x, ...) {
|
||||
+char** strv_new_internal(const char *x, ...) {
|
||||
char **r;
|
||||
va_list ap;
|
||||
|
||||
@@ -174,7 +172,7 @@ char **strv_new_internal(const char *x, ...) {
|
||||
|
||||
int strv_extend_strv(char ***a, char * const *b, bool filter_duplicates) {
|
||||
char * const *s, **t;
|
||||
- size_t p, q, i = 0, j;
|
||||
+ size_t p, q, i = 0;
|
||||
|
||||
assert(a);
|
||||
|
||||
@@ -195,7 +193,6 @@ int strv_extend_strv(char ***a, char * const *b, bool filter_duplicates) {
|
||||
*a = t;
|
||||
|
||||
STRV_FOREACH(s, b) {
|
||||
-
|
||||
if (filter_duplicates && strv_contains(t, *s))
|
||||
continue;
|
||||
|
||||
@@ -212,7 +209,7 @@ int strv_extend_strv(char ***a, char * const *b, bool filter_duplicates) {
|
||||
return (int) i;
|
||||
|
||||
rollback:
|
||||
- for (j = 0; j < i; j++)
|
||||
+ for (size_t j = 0; j < i; j++)
|
||||
free(t[p + j]);
|
||||
|
||||
t[p] = NULL;
|
||||
@@ -285,7 +282,6 @@ int strv_split_full(char ***t, const char *s, const char *separators, ExtractFla
|
||||
return -ENOMEM;
|
||||
|
||||
l[n++] = TAKE_PTR(word);
|
||||
-
|
||||
l[n] = NULL;
|
||||
}
|
||||
|
||||
@@ -352,7 +348,7 @@ int strv_split_colon_pairs(char ***t, const char *s) {
|
||||
return (int) n;
|
||||
}
|
||||
|
||||
-char *strv_join_full(char * const *l, const char *separator, const char *prefix, bool unescape_separators) {
|
||||
+char* strv_join_full(char * const *l, const char *separator, const char *prefix, bool unescape_separators) {
|
||||
char * const *s;
|
||||
char *r, *e;
|
||||
size_t n, k, m;
|
||||
@@ -459,7 +455,7 @@ int strv_push_pair(char ***l, char *a, char *b) {
|
||||
|
||||
int strv_insert(char ***l, size_t position, char *value) {
|
||||
char **c;
|
||||
- size_t n, m, i;
|
||||
+ size_t n, m;
|
||||
|
||||
if (!value)
|
||||
return 0;
|
||||
@@ -476,18 +472,14 @@ int strv_insert(char ***l, size_t position, char *value) {
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
- for (i = 0; i < position; i++)
|
||||
+ for (size_t i = 0; i < position; i++)
|
||||
c[i] = (*l)[i];
|
||||
c[position] = value;
|
||||
- for (i = position; i < n; i++)
|
||||
+ for (size_t i = position; i < n; i++)
|
||||
c[i+1] = (*l)[i];
|
||||
-
|
||||
c[n+1] = NULL;
|
||||
|
||||
- free(*l);
|
||||
- *l = c;
|
||||
-
|
||||
- return 0;
|
||||
+ return free_and_replace(*l, c);
|
||||
}
|
||||
|
||||
int strv_consume(char ***l, char *value) {
|
||||
@@ -584,7 +576,7 @@ int strv_extend_front(char ***l, const char *value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-char **strv_uniq(char **l) {
|
||||
+char** strv_uniq(char **l) {
|
||||
char **i;
|
||||
|
||||
/* Drops duplicate entries. The first identical string will be
|
||||
@@ -606,7 +598,7 @@ bool strv_is_uniq(char * const *l) {
|
||||
return true;
|
||||
}
|
||||
|
||||
-char **strv_remove(char **l, const char *s) {
|
||||
+char** strv_remove(char **l, const char *s) {
|
||||
char **f, **t;
|
||||
|
||||
if (!l)
|
||||
@@ -627,7 +619,7 @@ char **strv_remove(char **l, const char *s) {
|
||||
return l;
|
||||
}
|
||||
|
||||
-char **strv_parse_nulstr(const char *s, size_t l) {
|
||||
+char** strv_parse_nulstr(const char *s, size_t l) {
|
||||
/* l is the length of the input data, which will be split at NULs into
|
||||
* elements of the resulting strv. Hence, the number of items in the resulting strv
|
||||
* will be equal to one plus the number of NUL bytes in the l bytes starting at s,
|
||||
@@ -639,7 +631,6 @@ char **strv_parse_nulstr(const char *s, size_t l) {
|
||||
* empty strings in s.
|
||||
*/
|
||||
|
||||
- const char *p;
|
||||
size_t c = 0, i = 0;
|
||||
char **v;
|
||||
|
||||
@@ -648,7 +639,7 @@ char **strv_parse_nulstr(const char *s, size_t l) {
|
||||
if (l <= 0)
|
||||
return new0(char*, 1);
|
||||
|
||||
- for (p = s; p < s + l; p++)
|
||||
+ for (const char *p = s; p < s + l; p++)
|
||||
if (*p == 0)
|
||||
c++;
|
||||
|
||||
@@ -659,8 +650,7 @@ char **strv_parse_nulstr(const char *s, size_t l) {
|
||||
if (!v)
|
||||
return NULL;
|
||||
|
||||
- p = s;
|
||||
- while (p < s + l) {
|
||||
+ for (const char *p = s; p < s + l; ) {
|
||||
const char *e;
|
||||
|
||||
e = memchr(p, 0, s + l - p);
|
||||
@@ -684,7 +674,7 @@ char **strv_parse_nulstr(const char *s, size_t l) {
|
||||
return v;
|
||||
}
|
||||
|
||||
-char **strv_split_nulstr(const char *s) {
|
||||
+char** strv_split_nulstr(const char *s) {
|
||||
const char *i;
|
||||
char **r = NULL;
|
||||
|
||||
@@ -759,7 +749,7 @@ static int str_compare(char * const *a, char * const *b) {
|
||||
return strcmp(*a, *b);
|
||||
}
|
||||
|
||||
-char **strv_sort(char **l) {
|
||||
+char** strv_sort(char **l) {
|
||||
typesafe_qsort(l, strv_length(l), str_compare);
|
||||
return l;
|
||||
}
|
||||
@@ -808,20 +798,20 @@ int strv_extendf(char ***l, const char *format, ...) {
|
||||
return strv_consume(l, x);
|
||||
}
|
||||
|
||||
-char **strv_reverse(char **l) {
|
||||
- size_t n, i;
|
||||
+char** strv_reverse(char **l) {
|
||||
+ size_t n;
|
||||
|
||||
n = strv_length(l);
|
||||
if (n <= 1)
|
||||
return l;
|
||||
|
||||
- for (i = 0; i < n / 2; i++)
|
||||
+ for (size_t i = 0; i < n / 2; i++)
|
||||
SWAP_TWO(l[i], l[n-1-i]);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
-char **strv_shell_escape(char **l, const char *bad) {
|
||||
+char** strv_shell_escape(char **l, const char *bad) {
|
||||
char **s;
|
||||
|
||||
/* Escapes every character in every string in l that is in bad,
|
||||
@@ -852,19 +842,17 @@ bool strv_fnmatch_full(char* const* patterns, const char *s, int flags, size_t *
|
||||
return false;
|
||||
}
|
||||
|
||||
-char ***strv_free_free(char ***l) {
|
||||
- char ***i;
|
||||
-
|
||||
+char*** strv_free_free(char ***l) {
|
||||
if (!l)
|
||||
return NULL;
|
||||
|
||||
- for (i = l; *i; i++)
|
||||
+ for (char ***i = l; *i; i++)
|
||||
strv_free(*i);
|
||||
|
||||
return mfree(l);
|
||||
}
|
||||
|
||||
-char **strv_skip(char **l, size_t n) {
|
||||
+char** strv_skip(char **l, size_t n) {
|
||||
|
||||
while (n > 0) {
|
||||
if (strv_isempty(l))
|
||||
@@ -877,7 +865,7 @@ char **strv_skip(char **l, size_t n) {
|
||||
}
|
||||
|
||||
int strv_extend_n(char ***l, const char *value, size_t n) {
|
||||
- size_t i, j, k;
|
||||
+ size_t i, k;
|
||||
char **nl;
|
||||
|
||||
assert(l);
|
||||
@@ -904,15 +892,15 @@ int strv_extend_n(char ***l, const char *value, size_t n) {
|
||||
if (!nl[i])
|
||||
goto rollback;
|
||||
}
|
||||
-
|
||||
nl[i] = NULL;
|
||||
+
|
||||
return 0;
|
||||
|
||||
rollback:
|
||||
- for (j = k; j < i; j++)
|
||||
+ for (size_t j = k; j < i; j++)
|
||||
free(nl[j]);
|
||||
-
|
||||
nl[k] = NULL;
|
||||
+
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
diff --git a/src/basic/strv.h b/src/basic/strv.h
|
||||
index 911528f..8674bfd 100644
|
||||
--- a/src/basic/strv.h
|
||||
+++ b/src/basic/strv.h
|
||||
@@ -13,23 +13,23 @@
|
||||
#include "macro.h"
|
||||
#include "string-util.h"
|
||||
|
||||
-char *strv_find(char * const *l, const char *name) _pure_;
|
||||
-char *strv_find_case(char * const *l, const char *name) _pure_;
|
||||
-char *strv_find_prefix(char * const *l, const char *name) _pure_;
|
||||
-char *strv_find_startswith(char * const *l, const char *name) _pure_;
|
||||
+char* strv_find(char * const *l, const char *name) _pure_;
|
||||
+char* strv_find_case(char * const *l, const char *name) _pure_;
|
||||
+char* strv_find_prefix(char * const *l, const char *name) _pure_;
|
||||
+char* strv_find_startswith(char * const *l, const char *name) _pure_;
|
||||
|
||||
#define strv_contains(l, s) (!!strv_find((l), (s)))
|
||||
#define strv_contains_case(l, s) (!!strv_find_case((l), (s)))
|
||||
|
||||
-char **strv_free(char **l);
|
||||
+char** strv_free(char **l);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free);
|
||||
#define _cleanup_strv_free_ _cleanup_(strv_freep)
|
||||
|
||||
-char **strv_free_erase(char **l);
|
||||
+char** strv_free_erase(char **l);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free_erase);
|
||||
#define _cleanup_strv_free_erase_ _cleanup_(strv_free_erasep)
|
||||
|
||||
-char **strv_copy(char * const *l);
|
||||
+char** strv_copy(char * const *l);
|
||||
size_t strv_length(char * const *l) _pure_;
|
||||
|
||||
int strv_extend_strv(char ***a, char * const *b, bool filter_duplicates);
|
||||
@@ -50,8 +50,8 @@ int strv_consume(char ***l, char *value);
|
||||
int strv_consume_pair(char ***l, char *a, char *b);
|
||||
int strv_consume_prepend(char ***l, char *value);
|
||||
|
||||
-char **strv_remove(char **l, const char *s);
|
||||
-char **strv_uniq(char **l);
|
||||
+char** strv_remove(char **l, const char *s);
|
||||
+char** strv_uniq(char **l);
|
||||
bool strv_is_uniq(char * const *l);
|
||||
|
||||
int strv_compare(char * const *a, char * const *b);
|
||||
@@ -59,8 +59,8 @@ static inline bool strv_equal(char * const *a, char * const *b) {
|
||||
return strv_compare(a, b) == 0;
|
||||
}
|
||||
|
||||
-char **strv_new_internal(const char *x, ...) _sentinel_;
|
||||
-char **strv_new_ap(const char *x, va_list ap);
|
||||
+char** strv_new_internal(const char *x, ...) _sentinel_;
|
||||
+char** strv_new_ap(const char *x, va_list ap);
|
||||
#define strv_new(...) strv_new_internal(__VA_ARGS__, NULL)
|
||||
|
||||
#define STRV_IGNORE ((const char *) POINTER_MAX)
|
||||
@@ -74,7 +74,7 @@ static inline bool strv_isempty(char * const *l) {
|
||||
}
|
||||
|
||||
int strv_split_full(char ***t, const char *s, const char *separators, ExtractFlags flags);
|
||||
-static inline char **strv_split(const char *s, const char *separators) {
|
||||
+static inline char** strv_split(const char *s, const char *separators) {
|
||||
char **ret;
|
||||
|
||||
if (strv_split_full(&ret, s, separators, 0) < 0)
|
||||
@@ -84,7 +84,7 @@ static inline char **strv_split(const char *s, const char *separators) {
|
||||
}
|
||||
|
||||
int strv_split_newlines_full(char ***ret, const char *s, ExtractFlags flags);
|
||||
-static inline char **strv_split_newlines(const char *s) {
|
||||
+static inline char** strv_split_newlines(const char *s) {
|
||||
char **ret;
|
||||
|
||||
if (strv_split_newlines_full(&ret, s, 0) < 0)
|
||||
@@ -98,13 +98,13 @@ static inline char **strv_split_newlines(const char *s) {
|
||||
* string in the vector is an empty string. */
|
||||
int strv_split_colon_pairs(char ***t, const char *s);
|
||||
|
||||
-char *strv_join_full(char * const *l, const char *separator, const char *prefix, bool escape_separtor);
|
||||
+char* strv_join_full(char * const *l, const char *separator, const char *prefix, bool escape_separtor);
|
||||
static inline char *strv_join(char * const *l, const char *separator) {
|
||||
return strv_join_full(l, separator, NULL, false);
|
||||
}
|
||||
|
||||
-char **strv_parse_nulstr(const char *s, size_t l);
|
||||
-char **strv_split_nulstr(const char *s);
|
||||
+char** strv_parse_nulstr(const char *s, size_t l);
|
||||
+char** strv_split_nulstr(const char *s);
|
||||
int strv_make_nulstr(char * const *l, char **p, size_t *n);
|
||||
|
||||
static inline int strv_from_nulstr(char ***a, const char *nulstr) {
|
||||
@@ -133,7 +133,7 @@ bool strv_overlap(char * const *a, char * const *b) _pure_;
|
||||
#define STRV_FOREACH_PAIR(x, y, l) \
|
||||
for ((x) = (l), (y) = (x) ? (x+1) : NULL; (x) && *(x) && *(y); (x) += 2, (y) = (x + 1))
|
||||
|
||||
-char **strv_sort(char **l);
|
||||
+char** strv_sort(char **l);
|
||||
void strv_print(char * const *l);
|
||||
|
||||
#define strv_from_stdarg_alloca(first) \
|
||||
@@ -208,8 +208,8 @@ void strv_print(char * const *l);
|
||||
x; \
|
||||
x = *(++_l))
|
||||
|
||||
-char **strv_reverse(char **l);
|
||||
-char **strv_shell_escape(char **l, const char *bad);
|
||||
+char** strv_reverse(char **l);
|
||||
+char** strv_shell_escape(char **l, const char *bad);
|
||||
|
||||
bool strv_fnmatch_full(char* const* patterns, const char *s, int flags, size_t *matched_pos);
|
||||
static inline bool strv_fnmatch(char* const* patterns, const char *s) {
|
||||
@@ -222,10 +222,10 @@ static inline bool strv_fnmatch_or_empty(char* const* patterns, const char *s, i
|
||||
strv_fnmatch_full(patterns, s, flags, NULL);
|
||||
}
|
||||
|
||||
-char ***strv_free_free(char ***l);
|
||||
+char*** strv_free_free(char ***l);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(char***, strv_free_free);
|
||||
|
||||
-char **strv_skip(char **l, size_t n);
|
||||
+char** strv_skip(char **l, size_t n);
|
||||
|
||||
int strv_extend_n(char ***l, const char *value, size_t n);
|
||||
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,92 @@
|
||||
From 8db998981a4fefd0122bcf5f965726b63c9045c2 Mon Sep 17 00:00:00 2001
|
||||
From: Richard Phibel <rphibel@googlemail.com>
|
||||
Date: Tue, 23 May 2023 16:09:40 +0200
|
||||
Subject: [PATCH] core: Don't GC unit if it is in cgroup_empty_queue
|
||||
|
||||
The gc_unit_queue is dispatched before the cgroup_empty_queue. Because
|
||||
of this, when we enter in on_cgroup_empty_event, the unit in
|
||||
cgroup_empty_queue may already have been freed and we don't clean up the
|
||||
corresponding cgroup. With this change, we prevent the unit from being
|
||||
garbage collected if it is in the cgroup_empty_queue.
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd/commit/8db998981a4fefd0122bcf5f965726b63c9045c2
|
||||
|
||||
---
|
||||
src/core/unit.c | 3 ++
|
||||
test/units/testsuite-19.cleanup-slice.sh | 49 ++++++++++++++++++++++++
|
||||
2 files changed, 52 insertions(+)
|
||||
create mode 100755 test/units/testsuite-19.cleanup-slice.sh
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 90f87a95f5..84e9185e82 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -441,6 +441,9 @@ bool unit_may_gc(Unit *u) {
|
||||
if (u->perpetual)
|
||||
return false;
|
||||
|
||||
+ if (u->in_cgroup_empty_queue)
|
||||
+ return false;
|
||||
+
|
||||
if (sd_bus_track_count(u->bus_track) > 0)
|
||||
return false;
|
||||
|
||||
diff --git a/test/units/testsuite-19.cleanup-slice.sh b/test/units/testsuite-19.cleanup-slice.sh
|
||||
new file mode 100755
|
||||
index 0000000000..5d63160334
|
||||
--- /dev/null
|
||||
+++ b/test/units/testsuite-19.cleanup-slice.sh
|
||||
@@ -0,0 +1,49 @@
|
||||
+#!/usr/bin/env bash
|
||||
+# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
+set -eux
|
||||
+set -o pipefail
|
||||
+
|
||||
+# shellcheck source=test/units/util.sh
|
||||
+. "$(dirname "$0")"/util.sh
|
||||
+
|
||||
+export SYSTEMD_LOG_LEVEL=debug
|
||||
+
|
||||
+# Create service with KillMode=none inside a slice
|
||||
+cat <<EOF >/run/systemd/system/test19cleanup.service
|
||||
+[Unit]
|
||||
+Description=Test 19 cleanup Service
|
||||
+[Service]
|
||||
+Slice=test19cleanup.slice
|
||||
+Type=exec
|
||||
+ExecStart=sleep infinity
|
||||
+KillMode=none
|
||||
+EOF
|
||||
+cat <<EOF >/run/systemd/system/test19cleanup.slice
|
||||
+[Unit]
|
||||
+Description=Test 19 cleanup Slice
|
||||
+EOF
|
||||
+
|
||||
+# Start service
|
||||
+systemctl start test19cleanup.service
|
||||
+assert_rc 0 systemd-cgls /test19cleanup.slice
|
||||
+
|
||||
+pid=$(systemctl show --property MainPID --value test19cleanup)
|
||||
+ps "$pid"
|
||||
+
|
||||
+# Stop slice
|
||||
+# The sleep process will not be killed because of KillMode=none
|
||||
+# Since there is still a process running under it, the /test19cleanup.slice cgroup won't be removed
|
||||
+systemctl stop test19cleanup.slice
|
||||
+
|
||||
+ps "$pid"
|
||||
+
|
||||
+# Kill sleep process manually
|
||||
+kill -s TERM "$pid"
|
||||
+while kill -0 "$pid" 2>/dev/null; do sleep 0.1; done
|
||||
+
|
||||
+timeout 30 bash -c 'while systemd-cgls /test19cleanup.slice/test19cleanup.service >& /dev/null; do sleep .5; done'
|
||||
+assert_rc 1 systemd-cgls /test19cleanup.slice/test19cleanup.service
|
||||
+
|
||||
+# Check that empty cgroup /test19cleanup.slice has been removed
|
||||
+timeout 30 bash -c 'while systemd-cgls /test19cleanup.slice >& /dev/null; do sleep .5; done'
|
||||
+assert_rc 1 systemd-cgls /test19cleanup.slice
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,84 @@
|
||||
From af05bb971731fe7280e4e85fde71c2e671772c18 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 8 Jun 2023 11:11:49 +0200
|
||||
Subject: [PATCH] core: do not GC units/jobs that are in the D-Bus queue
|
||||
|
||||
Let's make sure that D-Bus messages are always sent out when pending,
|
||||
before we might GC a unit/job.
|
||||
|
||||
This is kinda a follow-up for 8db998981a4fefd0122bcf5f965726b63c9045c2,
|
||||
and a similar logic really applies: GC should only be done if we
|
||||
processed everything else, generated evertyhing else and really don't
|
||||
need it anymore.
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd/commit/af05bb971731fe7280e4e85fde71c2e671772c18
|
||||
|
||||
---
|
||||
src/core/dbus-job.c | 3 +++
|
||||
src/core/dbus-unit.c | 3 +++
|
||||
src/core/job.c | 4 ++++
|
||||
src/core/unit.c | 4 ++++
|
||||
4 files changed, 14 insertions(+)
|
||||
|
||||
diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c
|
||||
index 9792a5c44a..c88d8c2dd5 100644
|
||||
--- a/src/core/dbus-job.c
|
||||
+++ b/src/core/dbus-job.c
|
||||
@@ -241,6 +241,9 @@ void bus_job_send_change_signal(Job *j) {
|
||||
if (j->in_dbus_queue) {
|
||||
LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
|
||||
j->in_dbus_queue = false;
|
||||
+
|
||||
+ /* The job might be good to be GC once its pending signals have been sent */
|
||||
+ job_add_to_gc_queue(j);
|
||||
}
|
||||
|
||||
r = bus_foreach_bus(j->manager, j->bus_track, j->sent_dbus_new_signal ? send_changed_signal : send_new_signal, j);
|
||||
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
|
||||
index 59d541ebfe..629f08ebcc 100644
|
||||
--- a/src/core/dbus-unit.c
|
||||
+++ b/src/core/dbus-unit.c
|
||||
@@ -1648,6 +1648,9 @@ void bus_unit_send_change_signal(Unit *u) {
|
||||
if (u->in_dbus_queue) {
|
||||
LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
|
||||
u->in_dbus_queue = false;
|
||||
+
|
||||
+ /* The unit might be good to be GC once its pending signals have been sent */
|
||||
+ unit_add_to_gc_queue(u);
|
||||
}
|
||||
|
||||
if (!u->id)
|
||||
diff --git a/src/core/job.c b/src/core/job.c
|
||||
index f87b0f7c74..50f9581d72 100644
|
||||
--- a/src/core/job.c
|
||||
+++ b/src/core/job.c
|
||||
@@ -1444,6 +1444,10 @@ bool job_may_gc(Job *j) {
|
||||
if (!UNIT_VTABLE(j->unit)->gc_jobs)
|
||||
return false;
|
||||
|
||||
+ /* Make sure to send out pending D-Bus events before we unload the unit */
|
||||
+ if (j->in_dbus_queue)
|
||||
+ return false;
|
||||
+
|
||||
if (sd_bus_track_count(j->bus_track) > 0)
|
||||
return false;
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 80f398c309..7b2e8c5f5c 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -447,6 +447,10 @@ bool unit_may_gc(Unit *u) {
|
||||
if (u->in_cgroup_empty_queue || u->in_cgroup_oom_queue)
|
||||
return false;
|
||||
|
||||
+ /* Make sure to send out D-Bus events before we unload the unit */
|
||||
+ if (u->in_dbus_queue)
|
||||
+ return false;
|
||||
+
|
||||
if (sd_bus_track_count(u->bus_track) > 0)
|
||||
return false;
|
||||
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
From 47226e893b24f1aa84caaa6be266fb3c03442904 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 12 Apr 2023 20:51:23 +0200
|
||||
Subject: [PATCH] core: fix property getter method for NFileDescriptorStore bus
|
||||
property
|
||||
|
||||
Since da6053d0a7c16795e7fac1f9ba6694863918a597 this is a size_t, not an
|
||||
unsigned. The difference doesn't matter on LE archs, but it matters on
|
||||
BE (i.e. s390x), since we'll return entirely nonsensical data.
|
||||
|
||||
Let's fix that.
|
||||
|
||||
Follow-up-for: da6053d0a7c16795e7fac1f9ba6694863918a597
|
||||
|
||||
An embarassing bug introduced in 2018... That made me scratch my head
|
||||
for way too long, as it made #27135 fail on s390x while it passed
|
||||
everywhere else.
|
||||
|
||||
Conflict:Adaptation Context. ASSERT_PTR function adaptation.
|
||||
Reference:https://github.com/systemd/systemd/commit/47226e893b24f1aa84caaa6be266fb3c03442904
|
||||
|
||||
---
|
||||
src/core/dbus-service.c | 26 +++++++++++++++++++++++++-
|
||||
1 file changed, 25 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
|
||||
index 02628cd..c0ec277 100644
|
||||
--- a/src/core/dbus-service.c
|
||||
+++ b/src/core/dbus-service.c
|
||||
@@ -189,6 +189,30 @@ int bus_service_method_mount_image(sd_bus_message *message, void *userdata, sd_b
|
||||
return bus_service_method_mount(message, userdata, error, true);
|
||||
}
|
||||
|
||||
+#if __SIZEOF_SIZE_T__ == 8
|
||||
+static int property_get_size_as_uint32(
|
||||
+ sd_bus *bus,
|
||||
+ const char *path,
|
||||
+ const char *interface,
|
||||
+ const char *property,
|
||||
+ sd_bus_message *reply,
|
||||
+ void *userdata,
|
||||
+ sd_bus_error *error) {
|
||||
+
|
||||
+ size_t *value = userdata;
|
||||
+ assert(value);
|
||||
+ uint32_t sz = *value >= UINT32_MAX ? UINT32_MAX : (uint32_t) *value;
|
||||
+
|
||||
+ /* Returns a size_t as a D-Bus "u" type, i.e. as 32bit value, even if size_t is 64bit. We'll saturate if it doesn't fit. */
|
||||
+
|
||||
+ return sd_bus_message_append_basic(reply, 'u', &sz);
|
||||
+}
|
||||
+#elif __SIZEOF_SIZE_T__ == 4
|
||||
+#define property_get_size_as_uint32 ((sd_bus_property_get_t) NULL)
|
||||
+#else
|
||||
+#error "Unexpected size of size_t"
|
||||
+#endif
|
||||
+
|
||||
const sd_bus_vtable bus_service_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@@ -215,7 +239,7 @@ const sd_bus_vtable bus_service_vtable[] = {
|
||||
SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store_max), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
- SD_BUS_PROPERTY("NFileDescriptorStore", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store), 0),
|
||||
+ SD_BUS_PROPERTY("NFileDescriptorStore", "u", property_get_size_as_uint32, offsetof(Service, n_fd_store), 0),
|
||||
SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("StatusErrno", "i", bus_property_get_int, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
From 1ba84fef3c1e505cb1413ef446a85c0c7ec439c6 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 4 Apr 2023 13:42:08 +0200
|
||||
Subject: [PATCH] core: move runtime directory removal into release_resource
|
||||
handler
|
||||
|
||||
We already clear the various fds we keep from the release_resources()
|
||||
handler, let's also destroy the runtime dir from there if this
|
||||
preservation mode is selected.
|
||||
|
||||
This makes a minor semantic change: previously we'd keep a runtime
|
||||
directory around if RuntimeDirectoryPreserve=restart is selected and at
|
||||
least one JOB_START job was around. With this logic we'll keep it around
|
||||
a tiny bit longer: as long as any job for the unit is around.
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd/commit/1ba84fef3c1e505cb1413ef446a85c0c7ec439c6
|
||||
|
||||
---
|
||||
src/core/unit.c | 26 +++++++++++++++++++++++---
|
||||
1 file changed, 23 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 089213cf88..d632c34f98 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -396,6 +396,7 @@ static bool unit_success_failure_handler_has_jobs(Unit *unit) {
|
||||
|
||||
void unit_release_resources(Unit *u) {
|
||||
UnitActiveState state;
|
||||
+ ExecContext *ec;
|
||||
|
||||
assert(u);
|
||||
|
||||
@@ -412,6 +413,10 @@ void unit_release_resources(Unit *u) {
|
||||
if (unit_will_restart(u))
|
||||
return;
|
||||
|
||||
+ ec = unit_get_exec_context(u);
|
||||
+ if (ec && ec->runtime_directory_preserve_mode == EXEC_PRESERVE_RESTART)
|
||||
+ exec_context_destroy_runtime_directory(ec, u->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
|
||||
+
|
||||
if (UNIT_VTABLE(u)->release_resources)
|
||||
UNIT_VTABLE(u)->release_resources(u);
|
||||
}
|
||||
@@ -582,6 +587,21 @@ void unit_submit_to_stop_when_bound_queue(Unit *u) {
|
||||
u->in_stop_when_bound_queue = true;
|
||||
}
|
||||
|
||||
+static bool unit_can_release_resources(Unit *u) {
|
||||
+ ExecContext *ec;
|
||||
+
|
||||
+ assert(u);
|
||||
+
|
||||
+ if (UNIT_VTABLE(u)->release_resources)
|
||||
+ return true;
|
||||
+
|
||||
+ ec = unit_get_exec_context(u);
|
||||
+ if (ec && ec->runtime_directory_preserve_mode == EXEC_PRESERVE_RESTART)
|
||||
+ return true;
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
void unit_submit_to_release_resources_queue(Unit *u) {
|
||||
assert(u);
|
||||
|
||||
@@ -594,7 +614,7 @@ void unit_submit_to_release_resources_queue(Unit *u) {
|
||||
if (u->perpetual)
|
||||
return;
|
||||
|
||||
- if (!UNIT_VTABLE(u)->release_resources)
|
||||
+ if (!unit_can_release_resources(u))
|
||||
return;
|
||||
|
||||
LIST_PREPEND(release_resources_queue, u->manager->release_resources_queue, u);
|
||||
@@ -5863,8 +5883,8 @@ void unit_destroy_runtime_data(Unit *u, const ExecContext *context) {
|
||||
assert(u);
|
||||
assert(context);
|
||||
|
||||
- if (context->runtime_directory_preserve_mode == EXEC_PRESERVE_NO ||
|
||||
- (context->runtime_directory_preserve_mode == EXEC_PRESERVE_RESTART && !unit_will_restart(u)))
|
||||
+ /* EXEC_PRESERVE_RESTART is handled via unit_release_resources()! */
|
||||
+ if (context->runtime_directory_preserve_mode == EXEC_PRESERVE_NO)
|
||||
exec_context_destroy_runtime_directory(context, u->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
|
||||
|
||||
exec_context_destroy_credentials(context, u->manager->prefix[EXEC_DIRECTORY_RUNTIME], u->id);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,294 @@
|
||||
From 19dff6914dee94b36320dbfda94f60af30ac65c1 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Yuan <me@yhndnzj.com>
|
||||
Date: Thu, 26 Jan 2023 17:44:03 +0800
|
||||
Subject: [PATCH] core: support overriding NOTIFYACCESS= through sd-notify
|
||||
during runtime
|
||||
|
||||
Closes #25963
|
||||
|
||||
Conflict:Adaptation Context.
|
||||
Reference:https://github.com/systemd/systemd/commit/19dff6914dee94b36320dbfda94f60af30ac65c1
|
||||
|
||||
---
|
||||
man/org.freedesktop.systemd1.xml | 1 -
|
||||
man/sd_notify.xml | 10 +++++
|
||||
src/core/dbus-service.c | 4 +-
|
||||
src/core/service.c | 67 +++++++++++++++++++++++++++-----
|
||||
src/core/service.h | 6 +++
|
||||
src/systemd/sd-daemon.h | 4 ++
|
||||
6 files changed, 80 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml
|
||||
index ec2148d..40b5223 100644
|
||||
--- a/man/org.freedesktop.systemd1.xml
|
||||
+++ b/man/org.freedesktop.systemd1.xml
|
||||
@@ -2301,7 +2301,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
readonly s Restart = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s PIDFile = '...';
|
||||
- @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s NotifyAccess = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly t RestartUSec = ...;
|
||||
diff --git a/man/sd_notify.xml b/man/sd_notify.xml
|
||||
index 69e1b02..c00889b 100644
|
||||
--- a/man/sd_notify.xml
|
||||
+++ b/man/sd_notify.xml
|
||||
@@ -142,6 +142,16 @@
|
||||
system check…</literal></para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term>NOTIFYACCESS=…</term>
|
||||
+
|
||||
+ <listitem><para>Reset the access to the service status notification
|
||||
+ socket during runtime, overriding <varname>NotifyAccess=</varname> setting
|
||||
+ in the service unit file. See <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
+ for details, specifically <literal>NotifyAccess=</literal> for a list of
|
||||
+ accepted values.</para></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term>ERRNO=…</term>
|
||||
|
||||
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
|
||||
index c301948..115c256 100644
|
||||
--- a/src/core/dbus-service.c
|
||||
+++ b/src/core/dbus-service.c
|
||||
@@ -29,8 +29,8 @@
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
|
||||
-static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
|
||||
+static BUS_DEFINE_PROPERTY_GET2(property_get_notify_access, "s", Service, service_get_notify_access, notify_access_to_string);
|
||||
static BUS_DEFINE_PROPERTY_GET(property_get_timeout_abort_usec, "t", Service, service_timeout_abort_usec);
|
||||
static BUS_DEFINE_PROPERTY_GET(property_get_watchdog_usec, "t", Service, service_get_watchdog_usec);
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_timeout_failure_mode, service_timeout_failure_mode, ServiceTimeoutFailureMode);
|
||||
@@ -194,7 +194,7 @@ const sd_bus_vtable bus_service_vtable[] = {
|
||||
SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
- SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
+ SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index 9426060..f05cac8 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -124,6 +124,8 @@ static void service_init(Unit *u) {
|
||||
s->exec_context.keyring_mode = MANAGER_IS_SYSTEM(u->manager) ?
|
||||
EXEC_KEYRING_PRIVATE : EXEC_KEYRING_INHERIT;
|
||||
|
||||
+ s->notify_access_override = _NOTIFY_ACCESS_INVALID;
|
||||
+
|
||||
s->watchdog_original_usec = USEC_INFINITY;
|
||||
|
||||
s->oom_policy = _OOM_POLICY_INVALID;
|
||||
@@ -208,6 +210,15 @@ void service_release_socket_fd(Service *s) {
|
||||
s->socket_peer = socket_peer_unref(s->socket_peer);
|
||||
}
|
||||
|
||||
+static void service_override_notify_access(Service *s, NotifyAccess notify_access_override) {
|
||||
+ assert(s);
|
||||
+
|
||||
+ s->notify_access_override = notify_access_override;
|
||||
+
|
||||
+ log_unit_debug(UNIT(s), "notify_access=%s", notify_access_to_string(s->notify_access));
|
||||
+ log_unit_debug(UNIT(s), "notify_access_override=%s", notify_access_to_string(s->notify_access_override));
|
||||
+}
|
||||
+
|
||||
static void service_stop_watchdog(Service *s) {
|
||||
assert(s);
|
||||
|
||||
@@ -839,7 +850,7 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
prefix, yes_no(s->guess_main_pid),
|
||||
prefix, service_type_to_string(s->type),
|
||||
prefix, service_restart_to_string(s->restart),
|
||||
- prefix, notify_access_to_string(s->notify_access),
|
||||
+ prefix, notify_access_to_string(service_get_notify_access(s)),
|
||||
prefix, notify_state_to_string(s->notify_state),
|
||||
prefix, oom_policy_to_string(s->oom_policy));
|
||||
|
||||
@@ -1435,11 +1446,11 @@ static bool service_exec_needs_notify_socket(Service *s, ExecFlags flags) {
|
||||
|
||||
if (flags & EXEC_IS_CONTROL)
|
||||
/* A control process */
|
||||
- return IN_SET(s->notify_access, NOTIFY_EXEC, NOTIFY_ALL);
|
||||
+ return IN_SET(service_get_notify_access(s), NOTIFY_EXEC, NOTIFY_ALL);
|
||||
|
||||
/* We only spawn main processes and control processes, so any
|
||||
* process that is not a control process is a main process */
|
||||
- return s->notify_access != NOTIFY_NONE;
|
||||
+ return service_get_notify_access(s) != NOTIFY_NONE;
|
||||
}
|
||||
|
||||
static int service_spawn(
|
||||
@@ -1820,6 +1831,9 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
|
||||
/* The next restart might not be a manual stop, hence reset the flag indicating manual stops */
|
||||
s->forbid_restart = false;
|
||||
|
||||
+ /* Reset NotifyAccess override */
|
||||
+ s->notify_access_override = _NOTIFY_ACCESS_INVALID;
|
||||
+
|
||||
/* We want fresh tmpdirs in case service is started again immediately */
|
||||
s->exec_runtime = exec_runtime_unref(s->exec_runtime, true);
|
||||
|
||||
@@ -2318,6 +2332,8 @@ static void service_enter_restart(Service *s) {
|
||||
s->n_restarts ++;
|
||||
s->flush_n_restarts = false;
|
||||
|
||||
+ s->notify_access_override = _NOTIFY_ACCESS_INVALID;
|
||||
+
|
||||
log_unit_struct(UNIT(s), LOG_INFO,
|
||||
"MESSAGE_ID=" SD_MESSAGE_UNIT_RESTART_SCHEDULED_STR,
|
||||
LOG_UNIT_INVOCATION_ID(UNIT(s)),
|
||||
@@ -2498,6 +2514,7 @@ static int service_start(Unit *u) {
|
||||
s->status_text = mfree(s->status_text);
|
||||
s->status_errno = 0;
|
||||
|
||||
+ s->notify_access_override = _NOTIFY_ACCESS_INVALID;
|
||||
s->notify_state = NOTIFY_UNKNOWN;
|
||||
|
||||
s->watchdog_original_usec = s->watchdog_usec;
|
||||
@@ -2760,6 +2777,9 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
}
|
||||
}
|
||||
|
||||
+ if (s->notify_access_override >= 0)
|
||||
+ (void) serialize_item(f, "notify-access-override", notify_access_to_string(s->notify_access_override));
|
||||
+
|
||||
(void) serialize_dual_timestamp(f, "watchdog-timestamp", &s->watchdog_timestamp);
|
||||
(void) serialize_bool(f, "forbid-restart", s->forbid_restart);
|
||||
|
||||
@@ -3028,7 +3048,15 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
|
||||
deserialize_dual_timestamp(value, &s->main_exec_status.start_timestamp);
|
||||
else if (streq(key, "main-exec-status-exit"))
|
||||
deserialize_dual_timestamp(value, &s->main_exec_status.exit_timestamp);
|
||||
- else if (streq(key, "watchdog-timestamp"))
|
||||
+ else if (streq(key, "notify-access-override")) {
|
||||
+ NotifyAccess notify_access;
|
||||
+
|
||||
+ notify_access = notify_access_from_string(value);
|
||||
+ if (notify_access < 0)
|
||||
+ log_unit_debug(u, "Failed to parse notify-access-override value: %s", value);
|
||||
+ else
|
||||
+ s->notify_access_override = notify_access;
|
||||
+ } else if (streq(key, "watchdog-timestamp"))
|
||||
deserialize_dual_timestamp(value, &s->watchdog_timestamp);
|
||||
else if (streq(key, "forbid-restart")) {
|
||||
int b;
|
||||
@@ -3549,7 +3577,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
* has been received */
|
||||
if (f != SERVICE_SUCCESS)
|
||||
service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
|
||||
- else if (!s->remain_after_exit || s->notify_access == NOTIFY_MAIN)
|
||||
+ else if (!s->remain_after_exit || service_get_notify_access(s) == NOTIFY_MAIN)
|
||||
/* The service has never been and will never be active */
|
||||
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL);
|
||||
break;
|
||||
@@ -4007,12 +4035,14 @@ static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void
|
||||
static bool service_notify_message_authorized(Service *s, pid_t pid, FDSet *fds) {
|
||||
assert(s);
|
||||
|
||||
- if (s->notify_access == NOTIFY_NONE) {
|
||||
+ NotifyAccess notify_access = service_get_notify_access(s);
|
||||
+
|
||||
+ if (notify_access == NOTIFY_NONE) {
|
||||
log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception is disabled.", pid);
|
||||
return false;
|
||||
}
|
||||
|
||||
- if (s->notify_access == NOTIFY_MAIN && pid != s->main_pid) {
|
||||
+ if (notify_access == NOTIFY_MAIN && pid != s->main_pid) {
|
||||
if (s->main_pid != 0)
|
||||
log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT, pid, s->main_pid);
|
||||
else
|
||||
@@ -4021,7 +4051,7 @@ static bool service_notify_message_authorized(Service *s, pid_t pid, FDSet *fds)
|
||||
return false;
|
||||
}
|
||||
|
||||
- if (s->notify_access == NOTIFY_EXEC && pid != s->main_pid && pid != s->control_pid) {
|
||||
+ if (notify_access == NOTIFY_EXEC && pid != s->main_pid && pid != s->control_pid) {
|
||||
if (s->main_pid != 0 && s->control_pid != 0)
|
||||
log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT" and control PID "PID_FMT,
|
||||
pid, s->main_pid, s->control_pid);
|
||||
@@ -4063,7 +4093,7 @@ static void service_notify_message(
|
||||
assert(u);
|
||||
assert(ucred);
|
||||
|
||||
- if (!service_notify_message_authorized(SERVICE(u), ucred->pid, fds))
|
||||
+ if (!service_notify_message_authorized(s, ucred->pid, fds))
|
||||
return;
|
||||
|
||||
if (DEBUG_LOGGING) {
|
||||
@@ -4168,6 +4198,25 @@ static void service_notify_message(
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Interpret NOTIFYACCESS= */
|
||||
+ e = strv_find_startswith(tags, "NOTIFYACCESS=");
|
||||
+ if (e) {
|
||||
+ NotifyAccess notify_access;
|
||||
+
|
||||
+ notify_access = notify_access_from_string(e);
|
||||
+ if (notify_access < 0)
|
||||
+ log_unit_warning_errno(u, notify_access,
|
||||
+ "Failed to parse NOTIFYACCESS= field value '%s' in notification message, ignoring: %m", e);
|
||||
+
|
||||
+ /* We don't need to check whether the new access mode is more strict than what is
|
||||
+ * already in use, since only the privileged process is allowed to change it
|
||||
+ * in the first place. */
|
||||
+ if (service_get_notify_access(s) != notify_access) {
|
||||
+ service_override_notify_access(s, notify_access);
|
||||
+ notify_dbus = true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Interpret ERRNO= */
|
||||
e = strv_find_startswith(tags, "ERRNO=");
|
||||
if (e) {
|
||||
diff --git a/src/core/service.h b/src/core/service.h
|
||||
index 4a4ab8a..a65ade3 100644
|
||||
--- a/src/core/service.h
|
||||
+++ b/src/core/service.h
|
||||
@@ -184,6 +184,7 @@ struct Service {
|
||||
PathSpec *pid_file_pathspec;
|
||||
|
||||
NotifyAccess notify_access;
|
||||
+ NotifyAccess notify_access_override;
|
||||
NotifyState notify_state;
|
||||
|
||||
sd_bus_slot *bus_name_pid_lookup_slot;
|
||||
@@ -213,6 +214,11 @@ static inline usec_t service_timeout_abort_usec(Service *s) {
|
||||
return s->timeout_abort_set ? s->timeout_abort_usec : s->timeout_stop_usec;
|
||||
}
|
||||
|
||||
+static inline NotifyAccess service_get_notify_access(Service *s) {
|
||||
+ assert(s);
|
||||
+ return s->notify_access_override < 0 ? s->notify_access : s->notify_access_override;
|
||||
+}
|
||||
+
|
||||
static inline usec_t service_get_watchdog_usec(Service *s) {
|
||||
assert(s);
|
||||
return s->watchdog_override_enable ? s->watchdog_override_usec : s->watchdog_original_usec;
|
||||
diff --git a/src/systemd/sd-daemon.h b/src/systemd/sd-daemon.h
|
||||
index f42a5d8..a93ce9c 100644
|
||||
--- a/src/systemd/sd-daemon.h
|
||||
+++ b/src/systemd/sd-daemon.h
|
||||
@@ -195,6 +195,10 @@ int sd_is_mq(int fd, const char *path);
|
||||
readable error message. Example: "STATUS=Completed
|
||||
66% of file system check..."
|
||||
|
||||
+ NOTIFYACCESS=...
|
||||
+ Reset the access to the service status notification socket.
|
||||
+ Example: "NOTIFYACCESS=main"
|
||||
+
|
||||
ERRNO=... If a daemon fails, the errno-style error code,
|
||||
formatted as string. Example: "ERRNO=2" for ENOENT.
|
||||
|
||||
--
|
||||
2.33.0
|
||||
|
||||
27
backport-fd-util-introduce-dir_fd_is_root_or_cwd.patch
Normal file
27
backport-fd-util-introduce-dir_fd_is_root_or_cwd.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From e212f422796da9e626030289faf083407c8955df Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Sun, 2 Apr 2023 01:25:46 +0900
|
||||
Subject: [PATCH] fd-util: introduce dir_fd_is_root_or_cwd()
|
||||
|
||||
Conflict:Import only fcntl.h to prevent dependency failures.
|
||||
Reference:https://github.com/systemd/systemd/commit/e212f422796da9e626030289faf083407c8955df
|
||||
|
||||
---
|
||||
src/basic/fd-util.h | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
|
||||
index 9529a47..a08907e 100644
|
||||
--- a/src/basic/fd-util.h
|
||||
+++ b/src/basic/fd-util.h
|
||||
@@ -2,6 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <dirent.h>
|
||||
+#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
--
|
||||
2.33.0
|
||||
|
||||
52
backport-fdset-add-new-fdset_consume-helper.patch
Normal file
52
backport-fdset-add-new-fdset_consume-helper.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From e829f28c1bc6e6865261bfb3bc26089f50e0c7bd Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 29 Mar 2023 18:52:25 +0200
|
||||
Subject: [PATCH] fdset: add new fdset_consume() helper
|
||||
|
||||
Conflict:Context Adaptation. Delete the code that is not involved.
|
||||
Reference:https://github.com/systemd/systemd/commit/e829f28c1bc6e6865261bfb3bc26089f50e0c7bd
|
||||
|
||||
---
|
||||
src/shared/fdset.c | 13 +++++++++++++
|
||||
src/shared/fdset.h | 1 +
|
||||
2 files changed, 14 insertions(+)
|
||||
|
||||
diff --git a/src/shared/fdset.c b/src/shared/fdset.c
|
||||
index 443aa7f..68a465f 100644
|
||||
--- a/src/shared/fdset.c
|
||||
+++ b/src/shared/fdset.c
|
||||
@@ -81,6 +81,19 @@ int fdset_put(FDSet *s, int fd) {
|
||||
return set_put(MAKE_SET(s), FD_TO_PTR(fd));
|
||||
}
|
||||
|
||||
+int fdset_consume(FDSet *s, int fd) {
|
||||
+ int r;
|
||||
+
|
||||
+ assert(s);
|
||||
+ assert(fd >= 0);
|
||||
+
|
||||
+ r = fdset_put(s, fd);
|
||||
+ if (r < 0)
|
||||
+ safe_close(fd);
|
||||
+
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
int fdset_put_dup(FDSet *s, int fd) {
|
||||
int copy, r;
|
||||
|
||||
diff --git a/src/shared/fdset.h b/src/shared/fdset.h
|
||||
index e8a6b48..ac5ec76 100644
|
||||
--- a/src/shared/fdset.h
|
||||
+++ b/src/shared/fdset.h
|
||||
@@ -13,6 +13,7 @@ FDSet* fdset_new(void);
|
||||
FDSet* fdset_free(FDSet *s);
|
||||
|
||||
int fdset_put(FDSet *s, int fd);
|
||||
+int fdset_consume(FDSet *s, int fd);
|
||||
int fdset_put_dup(FDSet *s, int fd);
|
||||
|
||||
bool fdset_contains(FDSet *s, int fd);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,86 @@
|
||||
From bdcad22e8e508308032cba5f8c2d5c093adb7d87 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 28 Mar 2023 11:17:23 +0200
|
||||
Subject: [PATCH] fdset: add new helper to convert an fdset to an array
|
||||
|
||||
Conflict:fdset_close_others removes different code, but the end result is the same.
|
||||
Reference:https://github.com/systemd/systemd/commit/bdcad22e8e508308032cba5f8c2d5c093adb7d87
|
||||
|
||||
---
|
||||
src/shared/fdset.c | 39 ++++++++++++++++++++++++++++++---------
|
||||
src/shared/fdset.h | 2 ++
|
||||
2 files changed, 32 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/shared/fdset.c b/src/shared/fdset.c
|
||||
index 443aa7f..cb7a340 100644
|
||||
--- a/src/shared/fdset.c
|
||||
+++ b/src/shared/fdset.c
|
||||
@@ -236,22 +236,43 @@ fail:
|
||||
return r;
|
||||
}
|
||||
|
||||
-int fdset_close_others(FDSet *fds) {
|
||||
+int fdset_to_array(FDSet *fds, int **ret) {
|
||||
+ unsigned j = 0, m;
|
||||
void *e;
|
||||
- int *a = NULL;
|
||||
- size_t j = 0, m;
|
||||
+ int *a;
|
||||
|
||||
- m = fdset_size(fds);
|
||||
+ assert(ret);
|
||||
|
||||
- if (m > 0) {
|
||||
- a = newa(int, m);
|
||||
- SET_FOREACH(e, MAKE_SET(fds))
|
||||
- a[j++] = PTR_TO_FD(e);
|
||||
+ m = fdset_size(fds);
|
||||
+ if (m > INT_MAX) /* We want to be able to return an "int" */
|
||||
+ return -ENOMEM;
|
||||
+ if (m == 0) {
|
||||
+ *ret = NULL; /* suppress array allocation if empty */
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
+ a = new(int, m);
|
||||
+ if (!a)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ SET_FOREACH(e, MAKE_SET(fds))
|
||||
+ a[j++] = PTR_TO_FD(e);
|
||||
+
|
||||
assert(j == m);
|
||||
|
||||
- return close_all_fds(a, j);
|
||||
+ *ret = TAKE_PTR(a);
|
||||
+ return (int) m;
|
||||
+}
|
||||
+
|
||||
+int fdset_close_others(FDSet *fds) {
|
||||
+ _cleanup_free_ int *a = NULL;
|
||||
+ int n;
|
||||
+
|
||||
+ n = fdset_to_array(fds, &a);
|
||||
+ if (n < 0)
|
||||
+ return n;
|
||||
+
|
||||
+ return close_all_fds(a, n);
|
||||
}
|
||||
|
||||
unsigned fdset_size(FDSet *fds) {
|
||||
diff --git a/src/shared/fdset.h b/src/shared/fdset.h
|
||||
index e8a6b48..5f4304e 100644
|
||||
--- a/src/shared/fdset.h
|
||||
+++ b/src/shared/fdset.h
|
||||
@@ -24,6 +24,8 @@ int fdset_new_listen_fds(FDSet **ret, bool unset);
|
||||
|
||||
int fdset_cloexec(FDSet *fds, bool b);
|
||||
|
||||
+int fdset_to_array(FDSet *fds, int **ret);
|
||||
+
|
||||
int fdset_close_others(FDSet *fds);
|
||||
|
||||
unsigned fdset_size(FDSet *fds);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
From 082c67616511c7c08627eaf19af7e59a7f360479 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <luca.boccassi@microsoft.com>
|
||||
Date: Thu, 9 Dec 2021 22:16:19 +0000
|
||||
Subject: [PATCH] meson: exclude .gitattributes when using install_subdir
|
||||
|
||||
It picks the whole content of the directory by default, but we don't
|
||||
want to install .gitattributes files. Add it to all invocations, not
|
||||
just the ones on subdirs with .gitattributes, so that we don't regress
|
||||
in the future.
|
||||
|
||||
Fixes #21715
|
||||
|
||||
Conflict:Adaptation Context.
|
||||
Reference:https://github.com/systemd/systemd/commit/082c67616511c7c08627eaf19af7e59a7f360479
|
||||
|
||||
---
|
||||
test/meson.build | 18 ++++++++++++++++++
|
||||
1 file changed, 18 insertions(+)
|
||||
|
||||
diff --git a/test/meson.build b/test/meson.build
|
||||
index 6f8f257..8727e66 100644
|
||||
--- a/test/meson.build
|
||||
+++ b/test/meson.build
|
||||
@@ -4,36 +4,52 @@ if install_tests
|
||||
testdata_dir = testsdir + '/testdata/'
|
||||
|
||||
install_subdir('journal-data',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('units',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('test-execute',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('test-path',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('test-path-util',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('test-umount',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('test-network-generator-conversion',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('testsuite-04.units',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('testsuite-06.units',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('testsuite-10.units',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('testsuite-11.units',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('testsuite-16.units',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('testsuite-28.units',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('testsuite-30.units',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('testsuite-52.units',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('testsuite-63.units',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
|
||||
testsuite08_dir = testdata_dir + '/testsuite-08.units'
|
||||
@@ -50,6 +66,7 @@ if install_tests
|
||||
|
||||
if conf.get('ENABLE_RESOLVE') == 1
|
||||
install_subdir('test-resolve',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
endif
|
||||
|
||||
@@ -72,6 +89,7 @@ if install_tests and conf.get('ENABLE_SYSUSERS') == 1
|
||||
install_data(test_sysusers_sh,
|
||||
install_dir : testsdir)
|
||||
install_subdir('test-sysusers',
|
||||
+ exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
endif
|
||||
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,150 @@
|
||||
From 9175338e09de56c99cebf0b9f215f3e9e0016cb9 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 16 Feb 2023 15:42:49 +0100
|
||||
Subject: [PATCH] notify: add new --exec switch for chaining other commands to
|
||||
systemd-notify
|
||||
|
||||
This is useful in tests, so that we can first send a READY message and
|
||||
then continue doing something else without changing PID.
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd/commit/9175338e09de56c99cebf0b9f215f3e9e0016cb9
|
||||
|
||||
---
|
||||
src/notify/notify.c | 59 ++++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 56 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/notify/notify.c b/src/notify/notify.c
|
||||
index b1348383f5..7320ffebde 100644
|
||||
--- a/src/notify/notify.c
|
||||
+++ b/src/notify/notify.c
|
||||
@@ -31,6 +31,11 @@ static bool arg_booted = false;
|
||||
static uid_t arg_uid = UID_INVALID;
|
||||
static gid_t arg_gid = GID_INVALID;
|
||||
static bool arg_no_block = false;
|
||||
+static char **arg_env = NULL;
|
||||
+static char **arg_exec = NULL;
|
||||
+
|
||||
+STATIC_DESTRUCTOR_REGISTER(arg_env, strv_freep);
|
||||
+STATIC_DESTRUCTOR_REGISTER(arg_exec, strv_freep);
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
@@ -41,6 +46,7 @@ static int help(void) {
|
||||
return log_oom();
|
||||
|
||||
printf("%s [OPTIONS...] [VARIABLE=VALUE...]\n"
|
||||
+ "%s [OPTIONS...] --exec [VARIABLE=VALUE...] ; CMDLINE...\n"
|
||||
"\n%sNotify the init system about service status updates.%s\n\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
@@ -53,8 +59,10 @@ static int help(void) {
|
||||
" --status=TEXT Set status text\n"
|
||||
" --booted Check if the system was booted up with systemd\n"
|
||||
" --no-block Do not wait until operation finished\n"
|
||||
+ " --exec Execute command line separated by ';' once done\n"
|
||||
"\nSee the %s for details.\n",
|
||||
program_invocation_short_name,
|
||||
+ program_invocation_short_name,
|
||||
ansi_highlight(),
|
||||
ansi_normal(),
|
||||
link);
|
||||
@@ -93,7 +101,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_STATUS,
|
||||
ARG_BOOTED,
|
||||
ARG_UID,
|
||||
- ARG_NO_BLOCK
|
||||
+ ARG_NO_BLOCK,
|
||||
+ ARG_EXEC,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@@ -107,10 +116,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "booted", no_argument, NULL, ARG_BOOTED },
|
||||
{ "uid", required_argument, NULL, ARG_UID },
|
||||
{ "no-block", no_argument, NULL, ARG_NO_BLOCK },
|
||||
+ { "exec", no_argument, NULL, ARG_EXEC },
|
||||
{}
|
||||
};
|
||||
|
||||
- int c, r;
|
||||
+ bool do_exec = false;
|
||||
+ int c, r, n_env;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
@@ -183,6 +194,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_no_block = true;
|
||||
break;
|
||||
|
||||
+ case ARG_EXEC:
|
||||
+ do_exec = true;
|
||||
+ break;
|
||||
+
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
@@ -202,6 +217,32 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ if (do_exec) {
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = optind; i < argc; i++)
|
||||
+ if (streq(argv[i], ";"))
|
||||
+ break;
|
||||
+
|
||||
+ if (i >= argc)
|
||||
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "If --exec is used argument list must contain ';' separator, refusing.");
|
||||
+ if (i+1 == argc)
|
||||
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty command line specified after ';' separator, refusing");
|
||||
+
|
||||
+ arg_exec = strv_copy_n(argv + i + 1, argc - i - 1);
|
||||
+ if (!arg_exec)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ n_env = i - optind;
|
||||
+ } else
|
||||
+ n_env = argc - optind;
|
||||
+
|
||||
+ if (n_env > 0) {
|
||||
+ arg_env = strv_copy_n(argv + optind, n_env);
|
||||
+ if (!arg_env)
|
||||
+ return log_oom();
|
||||
+ }
|
||||
+
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -263,7 +304,7 @@ static int run(int argc, char* argv[]) {
|
||||
|
||||
our_env[i++] = NULL;
|
||||
|
||||
- final_env = strv_env_merge(our_env, argv + optind);
|
||||
+ final_env = strv_env_merge(our_env, arg_env);
|
||||
if (!final_env)
|
||||
return log_oom();
|
||||
|
||||
@@ -313,6 +354,18 @@ static int run(int argc, char* argv[]) {
|
||||
"No status data could be sent: $NOTIFY_SOCKET was not set");
|
||||
}
|
||||
|
||||
+ if (arg_exec) {
|
||||
+ _cleanup_free_ char *cmdline = NULL;
|
||||
+
|
||||
+ execvp(arg_exec[0], arg_exec);
|
||||
+
|
||||
+ cmdline = strv_join(arg_exec, " ");
|
||||
+ if (!cmdline)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ return log_error_errno(errno, "Failed to execute command line: %s", cmdline);
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,258 @@
|
||||
From 6e4a324574d5f1b2296799324dbdb54326078233 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 28 Mar 2023 11:17:44 +0200
|
||||
Subject: [PATCH] notify: add support for sending fds with notification
|
||||
messages
|
||||
|
||||
This exposes the fd passing we support via sd_pid_notify_with_fds() also
|
||||
via the command line tool systemd-notify.
|
||||
|
||||
Conflict:Context Adaptation. fdset_new_fill adaptation.
|
||||
Reference:https://github.com/systemd/systemd/commit/6e4a324574d5f1b2296799324dbdb54326078233
|
||||
|
||||
---
|
||||
man/systemd-notify.xml | 23 +++++++++
|
||||
src/notify/notify.c | 109 +++++++++++++++++++++++++++++++++++++++--
|
||||
2 files changed, 128 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/man/systemd-notify.xml b/man/systemd-notify.xml
|
||||
index 3fed92e..586d09e 100644
|
||||
--- a/man/systemd-notify.xml
|
||||
+++ b/man/systemd-notify.xml
|
||||
@@ -143,6 +143,29 @@
|
||||
this option set is prone to race conditions in all other cases.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><option>--fd=</option></term>
|
||||
+
|
||||
+ <listitem><para>Send a file descriptor along with the notification message. This is useful when
|
||||
+ invoked in services that have the <varname>FileDescriptorStoreMax=</varname> setting enabled, see
|
||||
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
+ for details. The specified file descriptor must be passed to <command>systemd-notify</command> when
|
||||
+ invoked. This option may be used multiple times to pass multiple file descriptors in a single
|
||||
+ notification message.</para>
|
||||
+
|
||||
+ <para>To use this functionality from a <command>bash</command> shell, use an expression like the following:</para>
|
||||
+ <programlisting>systemd-notify --fd=4 --fd=5 4</some/file 5</some/other/file</programlisting></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term><option>--fdname=</option></term>
|
||||
+
|
||||
+ <listitem><para>Set a name to assign to the file descriptors passed via <option>--fd=</option> (see
|
||||
+ above). This controls the <literal>FDNAME=</literal> field. This setting may only be specified once,
|
||||
+ and applies to all file descriptors passed. Invoke this tool multiple times in case multiple file
|
||||
+ descriptors with different file descriptor names shall be submitted.</para></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<xi:include href="standard-options.xml" xpointer="help" />
|
||||
<xi:include href="standard-options.xml" xpointer="version" />
|
||||
</variablelist>
|
||||
diff --git a/src/notify/notify.c b/src/notify/notify.c
|
||||
index 5afea7f..ad0ae89 100644
|
||||
--- a/src/notify/notify.c
|
||||
+++ b/src/notify/notify.c
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "env-util.h"
|
||||
+#include "fd-util.h"
|
||||
+#include "fdset.h"
|
||||
#include "format-util.h"
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
@@ -31,9 +33,13 @@ static gid_t arg_gid = GID_INVALID;
|
||||
static bool arg_no_block = false;
|
||||
static char **arg_env = NULL;
|
||||
static char **arg_exec = NULL;
|
||||
+static FDSet *arg_fds = NULL;
|
||||
+static char *arg_fdname = NULL;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_env, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_exec, strv_freep);
|
||||
+STATIC_DESTRUCTOR_REGISTER(arg_fds, fdset_freep);
|
||||
+STATIC_DESTRUCTOR_REGISTER(arg_fdname, freep);
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
@@ -55,6 +61,8 @@ static int help(void) {
|
||||
" --booted Check if the system was booted up with systemd\n"
|
||||
" --no-block Do not wait until operation finished\n"
|
||||
" --exec Execute command line separated by ';' once done\n"
|
||||
+ " --fd=FD Pass specified file descriptor with along with message\n"
|
||||
+ " --fdname=NAME Name to assign to passed file descriptor(s)\n"
|
||||
"\nSee the %s for details.\n",
|
||||
program_invocation_short_name,
|
||||
program_invocation_short_name,
|
||||
@@ -96,6 +104,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_UID,
|
||||
ARG_NO_BLOCK,
|
||||
ARG_EXEC,
|
||||
+ ARG_FD,
|
||||
+ ARG_FDNAME,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@@ -108,9 +118,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "uid", required_argument, NULL, ARG_UID },
|
||||
{ "no-block", no_argument, NULL, ARG_NO_BLOCK },
|
||||
{ "exec", no_argument, NULL, ARG_EXEC },
|
||||
+ { "fd", required_argument, NULL, ARG_FD },
|
||||
+ { "fdname", required_argument, NULL, ARG_FDNAME },
|
||||
{}
|
||||
};
|
||||
|
||||
+ _cleanup_(fdset_freep) FDSet *passed = NULL;
|
||||
bool do_exec = false;
|
||||
int c, r, n_env;
|
||||
|
||||
@@ -181,6 +194,60 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
do_exec = true;
|
||||
break;
|
||||
|
||||
+ case ARG_FD: {
|
||||
+ _cleanup_close_ int owned_fd = -EBADF;
|
||||
+ int fdnr;
|
||||
+
|
||||
+ r = safe_atoi(optarg, &fdnr);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to parse file descriptor: %s", optarg);
|
||||
+ if (fdnr < 0)
|
||||
+ return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "File descriptor can't be negative: %i", fdnr);
|
||||
+
|
||||
+ if (!passed) {
|
||||
+ /* Take possession of all passed fds */
|
||||
+ r = fdset_new_fill(/* filter_cloexec= */ 0, &passed);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to take possession of passed file descriptors: %m");
|
||||
+
|
||||
+ r = fdset_cloexec(passed, true);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to enable O_CLOEXEC for passed file descriptors: %m");
|
||||
+ }
|
||||
+
|
||||
+ if (fdnr < 3) {
|
||||
+ /* For stdin/stdout/stderr we want to keep the fd, too, hence make a copy */
|
||||
+ owned_fd = fcntl(fdnr, F_DUPFD_CLOEXEC, 3);
|
||||
+ if (owned_fd < 0)
|
||||
+ return log_error_errno(errno, "Failed to duplicate file descriptor: %m");
|
||||
+ } else {
|
||||
+ /* Otherwise, move the fd over */
|
||||
+ owned_fd = fdset_remove(passed, fdnr);
|
||||
+ if (owned_fd < 0)
|
||||
+ return log_error_errno(owned_fd, "Specified file descriptor '%i' not passed or specified more than once: %m", fdnr);
|
||||
+ }
|
||||
+
|
||||
+ if (!arg_fds) {
|
||||
+ arg_fds = fdset_new();
|
||||
+ if (!arg_fds)
|
||||
+ return log_oom();
|
||||
+ }
|
||||
+
|
||||
+ r = fdset_consume(arg_fds, TAKE_FD(owned_fd));
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to add file descriptor to set: %m");
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ case ARG_FDNAME:
|
||||
+ if (!fdname_is_valid(optarg))
|
||||
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File descriptor name invalid: %s", optarg);
|
||||
+
|
||||
+ if (free_and_strdup(&arg_fdname, optarg) < 0)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ break;
|
||||
+
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
@@ -193,11 +260,15 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
!arg_ready &&
|
||||
!arg_status &&
|
||||
!arg_pid &&
|
||||
- !arg_booted) {
|
||||
+ !arg_booted &&
|
||||
+ fdset_isempty(arg_fds)) {
|
||||
help();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ if (arg_fdname && fdset_isempty(arg_fds))
|
||||
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No file descriptors passed, but --fdname= set, refusing.");
|
||||
+
|
||||
if (do_exec) {
|
||||
int i;
|
||||
|
||||
@@ -224,13 +295,16 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
+ if (!fdset_isempty(passed))
|
||||
+ log_warning("Warning: %u more file descriptors passed than referenced with --fd=.", fdset_size(passed));
|
||||
+
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int run(int argc, char* argv[]) {
|
||||
- _cleanup_free_ char *status = NULL, *cpid = NULL, *n = NULL;
|
||||
+ _cleanup_free_ char *status = NULL, *cpid = NULL, *n = NULL, *fdn = NULL;
|
||||
_cleanup_strv_free_ char **final_env = NULL;
|
||||
- char* our_env[4];
|
||||
+ char* our_env[6];
|
||||
unsigned i = 0;
|
||||
pid_t source_pid;
|
||||
int r;
|
||||
@@ -271,6 +345,18 @@ static int run(int argc, char* argv[]) {
|
||||
our_env[i++] = cpid;
|
||||
}
|
||||
|
||||
+ if (!fdset_isempty(arg_fds)) {
|
||||
+ our_env[i++] = (char*) "FDSTORE=1";
|
||||
+
|
||||
+ if (arg_fdname) {
|
||||
+ fdn = strjoin("FDNAME=", arg_fdname);
|
||||
+ if (!fdn)
|
||||
+ return log_oom();
|
||||
+
|
||||
+ our_env[i++] = fdn;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
our_env[i++] = NULL;
|
||||
|
||||
final_env = strv_env_merge(our_env, arg_env);
|
||||
@@ -307,13 +393,28 @@ static int run(int argc, char* argv[]) {
|
||||
* or the service manager itself */
|
||||
source_pid = 0;
|
||||
}
|
||||
- r = sd_pid_notify(source_pid, false, n);
|
||||
+
|
||||
+ if (fdset_isempty(arg_fds))
|
||||
+ r = sd_pid_notify(source_pid, /* unset_environment= */ false, n);
|
||||
+ else {
|
||||
+ _cleanup_free_ int *a = NULL;
|
||||
+ int k;
|
||||
+
|
||||
+ k = fdset_to_array(arg_fds, &a);
|
||||
+ if (k < 0)
|
||||
+ return log_error_errno(k, "Failed to convert file descriptor set to array: %m");
|
||||
+
|
||||
+ r = sd_pid_notify_with_fds(source_pid, /* unset_environment= */ false, n, a, k);
|
||||
+
|
||||
+ }
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to notify init system: %m");
|
||||
if (r == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"No status data could be sent: $NOTIFY_SOCKET was not set");
|
||||
|
||||
+ arg_fds = fdset_free(arg_fds); /* Close before we execute anything */
|
||||
+
|
||||
if (!arg_no_block) {
|
||||
r = sd_notify_barrier(0, 5 * USEC_PER_SEC);
|
||||
if (r < 0)
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
From e8783d7620e4811738be078480aa5ffc9bbdcf9b Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 12 Apr 2023 21:07:29 +0200
|
||||
Subject: [PATCH] pid1: add some debug logging when stashing ds into the
|
||||
fdstore
|
||||
|
||||
Conflict:Context Adaptation. Log Adaptation.
|
||||
Reference:https://github.com/systemd/systemd/commit/e8783d7620e4811738be078480aa5ffc9bbdcf9b
|
||||
|
||||
---
|
||||
src/core/service.c | 13 ++++++++++---
|
||||
1 file changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index a7d5f3f..103c8a5 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -427,6 +427,7 @@ static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *us
|
||||
}
|
||||
|
||||
static int service_add_fd_store(Service *s, int fd, const char *name, bool do_poll) {
|
||||
+ struct stat st;
|
||||
ServiceFDStore *fs;
|
||||
int r;
|
||||
|
||||
@@ -435,16 +436,22 @@ static int service_add_fd_store(Service *s, int fd, const char *name, bool do_po
|
||||
assert(s);
|
||||
assert(fd >= 0);
|
||||
|
||||
+ if (fstat(fd, &st) < 0)
|
||||
+ return -errno;
|
||||
+
|
||||
+ log_unit_debug(UNIT(s), "Trying to stash fd for dev=" "%u:%u" "/inode=%" PRIu64, major(st.st_dev), minor(st.st_dev), (uint64_t) st.st_ino);
|
||||
+
|
||||
if (s->n_fd_store >= s->n_fd_store_max)
|
||||
- return -EXFULL; /* Our store is full.
|
||||
- * Use this errno rather than E[NM]FILE to distinguish from
|
||||
- * the case where systemd itself hits the file limit. */
|
||||
+ /* Our store is full. Use this errno rather than E[NM]FILE to distinguish from the case
|
||||
+ * where systemd itself hits the file limit. */
|
||||
+ return log_unit_debug_errno(UNIT(s), SYNTHETIC_ERRNO(EXFULL), "Hit fd store limit.");
|
||||
|
||||
LIST_FOREACH(fd_store, fs, s->fd_store) {
|
||||
r = same_fd(fs->fd, fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0) {
|
||||
+ log_unit_debug(UNIT(s), "Suppressing duplicate fd in fd store.");
|
||||
asynchronous_close(fd);
|
||||
return 0; /* fd already included */
|
||||
}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
476
backport-service-add-ability-to-pin-fd-store.patch
Normal file
476
backport-service-add-ability-to-pin-fd-store.patch
Normal file
@ -0,0 +1,476 @@
|
||||
From b9c1883a9cd9b5126fe648f3e198143dc19a222d Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 29 Mar 2023 22:07:22 +0200
|
||||
Subject: [PATCH] service: add ability to pin fd store
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Oftentimes it is useful to allow the per-service fd store to survive
|
||||
longer than for a restart. This is useful in various scenarios:
|
||||
|
||||
1. An fd to some security relevant object needs to be stashed somewhere,
|
||||
that should not be cleaned automatically, because the security
|
||||
enforcement would be dropped then.
|
||||
|
||||
2. A user namespace fd should be allocated on first invocation and be
|
||||
kept around until the user logs out (i.e. systemd --user ends), á la
|
||||
#16328 (This does not implement what #16318 asks for, but should
|
||||
solve the use-case discussed there.)
|
||||
|
||||
3. There's interest in allow a concept of "userspace reboots" where the
|
||||
kernel stays running, and userspace is swapped out (i.e. all services
|
||||
exit, and the rootfs transitioned into a new version of it) while
|
||||
keeping some select resources pinned, very similar to how we
|
||||
implement a switch root. Thus it is useful to allow services to exit,
|
||||
while leaving their fds around till the very end.
|
||||
|
||||
This is exposed through a new FileDescriptorStorePreserve= setting that
|
||||
is closely modelled after RuntimeDirectoryPreserve= (in fact it reused
|
||||
the same internal type), since we want similar behaviour in the end, and
|
||||
quite often they probably want to be used together.
|
||||
|
||||
Conflict:Adaptation Context.The FileDescriptorStorePreserve= field is added to the directives.service file to prevent test case failures.
|
||||
Reference:https://github.com/systemd/systemd/commit/b9c1883a9cd9b5126fe648f3e198143dc19a222d
|
||||
|
||||
---
|
||||
man/org.freedesktop.systemd1.xml | 6 +++
|
||||
man/systemd.service.xml | 21 +++++++++-
|
||||
src/basic/unit-def.c | 1 +
|
||||
src/basic/unit-def.h | 1 +
|
||||
src/core/dbus-execute.c | 8 ++--
|
||||
src/core/dbus-execute.h | 2 +
|
||||
src/core/dbus-service.c | 4 ++
|
||||
src/core/load-fragment-gperf.gperf.in | 3 +-
|
||||
src/core/load-fragment.c | 2 +-
|
||||
src/core/load-fragment.h | 2 +-
|
||||
src/core/service.c | 43 ++++++++++++++++-----
|
||||
src/core/service.h | 1 +
|
||||
src/shared/bus-unit-util.c | 3 +-
|
||||
test/fuzz/fuzz-unit-file/directives.service | 1 +
|
||||
14 files changed, 78 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml
|
||||
index 74a9202..ec2148d 100644
|
||||
--- a/man/org.freedesktop.systemd1.xml
|
||||
+++ b/man/org.freedesktop.systemd1.xml
|
||||
@@ -2343,6 +2343,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
readonly u FileDescriptorStoreMax = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
|
||||
readonly u NFileDescriptorStore = ...;
|
||||
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
|
||||
+ readonly s FileDescriptorStorePreserve = '...';
|
||||
readonly s StatusText = '...';
|
||||
readonly i StatusErrno = ...;
|
||||
readonly s Result = '...';
|
||||
@@ -2898,6 +2900,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
|
||||
<!--property NFileDescriptorStore is not documented!-->
|
||||
|
||||
+ <!--property FileDescriptorStorePreserve is not documented!-->
|
||||
+
|
||||
<!--property StatusErrno is not documented!-->
|
||||
|
||||
<!--property ReloadResult is not documented!-->
|
||||
@@ -3430,6 +3434,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="NFileDescriptorStore"/>
|
||||
|
||||
+ <variablelist class="dbus-property" generated="True" extra-ref="FileDescriptorStorePreserve"/>
|
||||
+
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="StatusText"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="StatusErrno"/>
|
||||
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
|
||||
index 350bc5f..ed9b410 100644
|
||||
--- a/man/systemd.service.xml
|
||||
+++ b/man/systemd.service.xml
|
||||
@@ -1050,7 +1050,7 @@
|
||||
<literal>FDSTORE=1</literal> messages. This is useful for implementing services that can restart
|
||||
after an explicit request or a crash without losing state. Any open sockets and other file
|
||||
descriptors which should not be closed during the restart may be stored this way. Application state
|
||||
- can either be serialized to a file in <filename>/run/</filename>, or better, stored in a
|
||||
+ can either be serialized to a file in <varname>RuntimeDirectory=</varname>, or stored in a
|
||||
<citerefentry><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
||||
memory file descriptor. Defaults to 0, i.e. no file descriptors may be stored in the service
|
||||
manager. All file descriptors passed to the service manager from a specific service are passed back
|
||||
@@ -1059,12 +1059,29 @@
|
||||
details about the precise protocol used and the order in which the file descriptors are passed). Any
|
||||
file descriptors passed to the service manager are automatically closed when
|
||||
<constant>POLLHUP</constant> or <constant>POLLERR</constant> is seen on them, or when the service is
|
||||
- fully stopped and no job is queued or being executed for it. If this option is used,
|
||||
+ fully stopped and no job is queued or being executed for it (the latter can be tweaked with
|
||||
+ <varname>FileDescriptorStorePreserve=</varname>, see below). If this option is used,
|
||||
<varname>NotifyAccess=</varname> (see above) should be set to open access to the notification socket
|
||||
provided by systemd. If <varname>NotifyAccess=</varname> is not set, it will be implicitly set to
|
||||
<option>main</option>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
+ <varlistentry>
|
||||
+ <term><varname>FileDescriptorStorePreserve=</varname></term>
|
||||
+ <listitem><para>Takes one of <constant>no</constant>, <constant>yes</constant>,
|
||||
+ <constant>restart</constant> and controls when to release the service's file descriptor store
|
||||
+ (i.e. when to close the contained file descriptors, if any). If set to <constant>no</constant> the
|
||||
+ file descriptor store is automatically released when the service is stopped; if
|
||||
+ <constant>restart</constant> (the default) it is kept around as long as the unit is neither inactive
|
||||
+ nor failed, or a job is queued for the service, or the service is expected to be restarted. If
|
||||
+ <constant>yes</constant> the file descriptor store is kept around until the unit is removed from
|
||||
+ memory (i.e. is not referenced anymore and inactive). The latter is useful to keep entries in the
|
||||
+ file descriptor store pinned until the service manage exits.</para>
|
||||
+
|
||||
+ <para>Use <command>systemctl clean --what=fdstore …</command> to release the file descriptor store
|
||||
+ explicitly.</para></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
<varlistentry>
|
||||
<term><varname>USBFunctionDescriptors=</varname></term>
|
||||
<listitem><para>Configure the location of a file containing
|
||||
diff --git a/src/basic/unit-def.c b/src/basic/unit-def.c
|
||||
index 2667e61..09b2747 100644
|
||||
--- a/src/basic/unit-def.c
|
||||
+++ b/src/basic/unit-def.c
|
||||
@@ -196,6 +196,7 @@ static const char* const service_state_table[_SERVICE_STATE_MAX] = {
|
||||
[SERVICE_FINAL_SIGTERM] = "final-sigterm",
|
||||
[SERVICE_FINAL_SIGKILL] = "final-sigkill",
|
||||
[SERVICE_FAILED] = "failed",
|
||||
+ [SERVICE_DEAD_RESOURCES_PINNED] = "dead-resources-pinned",
|
||||
[SERVICE_AUTO_RESTART] = "auto-restart",
|
||||
[SERVICE_CLEANING] = "cleaning",
|
||||
};
|
||||
diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h
|
||||
index 08651ef..c9e41bd 100644
|
||||
--- a/src/basic/unit-def.h
|
||||
+++ b/src/basic/unit-def.h
|
||||
@@ -141,6 +141,7 @@ typedef enum ServiceState {
|
||||
SERVICE_FINAL_SIGTERM, /* In case the STOP_POST executable hangs, we shoot that down, too */
|
||||
SERVICE_FINAL_SIGKILL,
|
||||
SERVICE_FAILED,
|
||||
+ SERVICE_DEAD_RESOURCES_PINNED, /* Like SERVICE_DEAD, but with pinned resources */
|
||||
SERVICE_AUTO_RESTART,
|
||||
SERVICE_CLEANING,
|
||||
_SERVICE_STATE_MAX,
|
||||
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
|
||||
index d8931c1..97277ca 100644
|
||||
--- a/src/core/dbus-execute.c
|
||||
+++ b/src/core/dbus-execute.c
|
||||
@@ -46,7 +46,7 @@
|
||||
BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode);
|
||||
-static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_preserve_mode, exec_preserve_mode, ExecPreserveMode);
|
||||
+BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_preserve_mode, exec_preserve_mode, ExecPreserveMode);
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode);
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_protect_proc, protect_proc, ProtectProc);
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_proc_subset, proc_subset, ProcSubset);
|
||||
@@ -1181,7 +1181,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_PROPERTY("Personality", "s", property_get_personality, offsetof(ExecContext, personality), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("LockPersonality", "b", bus_property_get_bool, offsetof(ExecContext, lock_personality), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
- SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", property_get_exec_preserve_mode, offsetof(ExecContext, runtime_directory_preserve_mode), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
+ SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", bus_property_get_exec_preserve_mode, offsetof(ExecContext, runtime_directory_preserve_mode), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].mode), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].paths), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("StateDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@@ -1551,7 +1551,7 @@ static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_home, ProtectHome, protect_home_fr
|
||||
static BUS_DEFINE_SET_TRANSIENT_PARSE(keyring_mode, ExecKeyringMode, exec_keyring_mode_from_string);
|
||||
static BUS_DEFINE_SET_TRANSIENT_PARSE(protect_proc, ProtectProc, protect_proc_from_string);
|
||||
static BUS_DEFINE_SET_TRANSIENT_PARSE(proc_subset, ProcSubset, proc_subset_from_string);
|
||||
-static BUS_DEFINE_SET_TRANSIENT_PARSE(preserve_mode, ExecPreserveMode, exec_preserve_mode_from_string);
|
||||
+BUS_DEFINE_SET_TRANSIENT_PARSE(exec_preserve_mode, ExecPreserveMode, exec_preserve_mode_from_string);
|
||||
static BUS_DEFINE_SET_TRANSIENT_PARSE_PTR(personality, unsigned long, parse_personality);
|
||||
static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(secure_bits, "i", int32_t, int, "%" PRIi32, secure_bits_to_string_alloc_with_check);
|
||||
static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(capability, "t", uint64_t, uint64_t, "%" PRIu64, capability_set_to_string_alloc);
|
||||
@@ -1842,7 +1842,7 @@ int bus_exec_context_set_transient_property(
|
||||
return bus_set_transient_proc_subset(u, name, &c->proc_subset, message, flags, error);
|
||||
|
||||
if (streq(name, "RuntimeDirectoryPreserve"))
|
||||
- return bus_set_transient_preserve_mode(u, name, &c->runtime_directory_preserve_mode, message, flags, error);
|
||||
+ return bus_set_transient_exec_preserve_mode(u, name, &c->runtime_directory_preserve_mode, message, flags, error);
|
||||
|
||||
if (streq(name, "UMask"))
|
||||
return bus_set_transient_mode_t(u, name, &c->umask, message, flags, error);
|
||||
diff --git a/src/core/dbus-execute.h b/src/core/dbus-execute.h
|
||||
index c538341..5926bdb 100644
|
||||
--- a/src/core/dbus-execute.h
|
||||
+++ b/src/core/dbus-execute.h
|
||||
@@ -28,6 +28,8 @@ int bus_property_get_exec_output(sd_bus *bus, const char *path, const char *inte
|
||||
int bus_property_get_exec_command(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);
|
||||
int bus_property_get_exec_command_list(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);
|
||||
int bus_property_get_exec_ex_command_list(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);
|
||||
+int bus_property_get_exec_preserve_mode(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);
|
||||
|
||||
int bus_exec_context_set_transient_property(Unit *u, ExecContext *c, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
int bus_set_transient_exec_command(Unit *u, const char *name, ExecCommand **exec_command, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
+int bus_set_transient_exec_preserve_mode(Unit *u, const char *name, ExecPreserveMode *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
|
||||
index c0ec277..4b05968 100644
|
||||
--- a/src/core/dbus-service.c
|
||||
+++ b/src/core/dbus-service.c
|
||||
@@ -240,6 +240,7 @@ const sd_bus_vtable bus_service_vtable[] = {
|
||||
SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store_max), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("NFileDescriptorStore", "u", property_get_size_as_uint32, offsetof(Service, n_fd_store), 0),
|
||||
+ SD_BUS_PROPERTY("FileDescriptorStorePreserve", "s", bus_property_get_exec_preserve_mode, offsetof(Service, fd_store_preserve_mode), 0),
|
||||
SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("StatusErrno", "i", bus_property_get_int, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
@@ -477,6 +478,9 @@ static int bus_service_set_transient_property(
|
||||
if (streq(name, "FileDescriptorStoreMax"))
|
||||
return bus_set_transient_unsigned(u, name, &s->n_fd_store_max, message, flags, error);
|
||||
|
||||
+ if (streq(name, "FileDescriptorStorePreserve"))
|
||||
+ return bus_set_transient_exec_preserve_mode(u, name, &s->fd_store_preserve_mode, message, flags, error);
|
||||
+
|
||||
if (streq(name, "NotifyAccess"))
|
||||
return bus_set_transient_notify_access(u, name, &s->notify_access, message, flags, error);
|
||||
|
||||
diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in
|
||||
index 42441ea..49e036f 100644
|
||||
--- a/src/core/load-fragment-gperf.gperf.in
|
||||
+++ b/src/core/load-fragment-gperf.gperf.in
|
||||
@@ -127,7 +127,7 @@
|
||||
{{type}}.MountFlags, config_parse_exec_mount_flags, 0, offsetof({{type}}, exec_context.mount_flags)
|
||||
{{type}}.MountAPIVFS, config_parse_exec_mount_apivfs, 0, offsetof({{type}}, exec_context)
|
||||
{{type}}.Personality, config_parse_personality, 0, offsetof({{type}}, exec_context.personality)
|
||||
-{{type}}.RuntimeDirectoryPreserve, config_parse_runtime_preserve_mode, 0, offsetof({{type}}, exec_context.runtime_directory_preserve_mode)
|
||||
+{{type}}.RuntimeDirectoryPreserve, config_parse_exec_preserve_mode, 0, offsetof({{type}}, exec_context.runtime_directory_preserve_mode)
|
||||
{{type}}.RuntimeDirectoryMode, config_parse_mode, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_RUNTIME].mode)
|
||||
{{type}}.RuntimeDirectory, config_parse_exec_directories, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_RUNTIME].paths)
|
||||
{{type}}.StateDirectoryMode, config_parse_mode, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_STATE].mode)
|
||||
@@ -395,6 +395,7 @@ Service.SysVStartPriority, config_parse_warn_compat,
|
||||
Service.NonBlocking, config_parse_bool, 0, offsetof(Service, exec_context.non_blocking)
|
||||
Service.BusName, config_parse_bus_name, 0, offsetof(Service, bus_name)
|
||||
Service.FileDescriptorStoreMax, config_parse_unsigned, 0, offsetof(Service, n_fd_store_max)
|
||||
+Service.FileDescriptorStorePreserve, config_parse_exec_preserve_mode, 0, offsetof(Service, fd_store_preserve_mode)
|
||||
Service.NotifyAccess, config_parse_notify_access, 0, offsetof(Service, notify_access)
|
||||
Service.Sockets, config_parse_service_sockets, 0, 0
|
||||
Service.BusPolicy, config_parse_warn_compat, DISABLED_LEGACY, 0
|
||||
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
|
||||
index f357408..7e5f919 100644
|
||||
--- a/src/core/load-fragment.c
|
||||
+++ b/src/core/load-fragment.c
|
||||
@@ -133,7 +133,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to pa
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_home, protect_home, ProtectHome, "Failed to parse protect home value");
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_system, protect_system, ProtectSystem, "Failed to parse protect system value");
|
||||
-DEFINE_CONFIG_PARSE_ENUM(config_parse_runtime_preserve_mode, exec_preserve_mode, ExecPreserveMode, "Failed to parse runtime directory preserve mode");
|
||||
+DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_preserve_mode, exec_preserve_mode, ExecPreserveMode, "Failed to parse resource preserve mode");
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_service_timeout_failure_mode, service_timeout_failure_mode, ServiceTimeoutFailureMode, "Failed to parse timeout failure mode");
|
||||
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
|
||||
index 45e9c39..974bb42 100644
|
||||
--- a/src/core/load-fragment.h
|
||||
+++ b/src/core/load-fragment.h
|
||||
@@ -93,7 +93,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_selinux_context);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_apparmor_profile);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_smack_process_label);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_address_families);
|
||||
-CONFIG_PARSER_PROTOTYPE(config_parse_runtime_preserve_mode);
|
||||
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_preserve_mode);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_directories);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_set_credential);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_load_credential);
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index af6360e..9f16790 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -60,6 +60,7 @@ static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
|
||||
[SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
|
||||
[SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
|
||||
[SERVICE_FAILED] = UNIT_FAILED,
|
||||
+ [SERVICE_DEAD_RESOURCES_PINNED] = UNIT_INACTIVE,
|
||||
[SERVICE_AUTO_RESTART] = UNIT_ACTIVATING,
|
||||
[SERVICE_CLEANING] = UNIT_MAINTENANCE,
|
||||
};
|
||||
@@ -84,6 +85,7 @@ static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] =
|
||||
[SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
|
||||
[SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
|
||||
[SERVICE_FAILED] = UNIT_FAILED,
|
||||
+ [SERVICE_DEAD_RESOURCES_PINNED] = UNIT_INACTIVE,
|
||||
[SERVICE_AUTO_RESTART] = UNIT_ACTIVATING,
|
||||
[SERVICE_CLEANING] = UNIT_MAINTENANCE,
|
||||
};
|
||||
@@ -121,6 +123,8 @@ static void service_init(Unit *u) {
|
||||
s->watchdog_original_usec = USEC_INFINITY;
|
||||
|
||||
s->oom_policy = _OOM_POLICY_INVALID;
|
||||
+
|
||||
+ s->fd_store_preserve_mode = EXEC_PRESERVE_RESTART;
|
||||
}
|
||||
|
||||
static void service_unwatch_control_pid(Service *s) {
|
||||
@@ -906,8 +910,10 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
if (s->n_fd_store_max > 0)
|
||||
fprintf(f,
|
||||
"%sFile Descriptor Store Max: %u\n"
|
||||
+ "%sFile Descriptor Store Pin: %s\n"
|
||||
"%sFile Descriptor Store Current: %zu\n",
|
||||
prefix, s->n_fd_store_max,
|
||||
+ prefix, exec_preserve_mode_to_string(s->fd_store_preserve_mode),
|
||||
prefix, s->n_fd_store);
|
||||
|
||||
cgroup_context_dump(UNIT(s), f, prefix);
|
||||
@@ -1101,7 +1107,7 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
|
||||
}
|
||||
|
||||
- if (IN_SET(state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)) {
|
||||
+ if (IN_SET(state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART, SERVICE_DEAD_RESOURCES_PINNED)) {
|
||||
unit_unwatch_all_pids(UNIT(s));
|
||||
unit_dequeue_rewatch_pids(UNIT(s));
|
||||
}
|
||||
@@ -1202,7 +1208,8 @@ static int service_coldplug(Unit *u) {
|
||||
return r;
|
||||
}
|
||||
|
||||
- if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART, SERVICE_CLEANING)) {
|
||||
+ if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART, SERVICE_CLEANING,
|
||||
+ SERVICE_DEAD_RESOURCES_PINNED)) {
|
||||
(void) unit_enqueue_rewatch_pids(u);
|
||||
(void) unit_setup_dynamic_creds(u);
|
||||
(void) unit_setup_exec_runtime(u);
|
||||
@@ -1718,6 +1725,12 @@ static bool service_will_restart(Unit *u) {
|
||||
return unit_will_restart_default(u);
|
||||
}
|
||||
|
||||
+static ServiceState service_determine_dead_state(Service *s) {
|
||||
+ assert(s);
|
||||
+
|
||||
+ return s->fd_store && s->fd_store_preserve_mode == EXEC_PRESERVE_YES ? SERVICE_DEAD_RESOURCES_PINNED : SERVICE_DEAD;
|
||||
+}
|
||||
+
|
||||
static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) {
|
||||
ServiceState end_state;
|
||||
int r;
|
||||
@@ -1734,10 +1747,10 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
|
||||
|
||||
if (s->result == SERVICE_SUCCESS) {
|
||||
unit_log_success(UNIT(s));
|
||||
- end_state = SERVICE_DEAD;
|
||||
+ end_state = service_determine_dead_state(s);
|
||||
} else if (s->result == SERVICE_SKIP_CONDITION) {
|
||||
unit_log_skip(UNIT(s), service_result_to_string(s->result));
|
||||
- end_state = SERVICE_DEAD;
|
||||
+ end_state = service_determine_dead_state(s);
|
||||
} else {
|
||||
unit_log_failure(UNIT(s), service_result_to_string(s->result));
|
||||
end_state = SERVICE_FAILED;
|
||||
@@ -1793,6 +1806,10 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
|
||||
/* Also, remove the runtime directory */
|
||||
unit_destroy_runtime_data(UNIT(s), &s->exec_context);
|
||||
|
||||
+ /* Also get rid of the fd store, if that's configured. */
|
||||
+ if (s->fd_store_preserve_mode == EXEC_PRESERVE_NO)
|
||||
+ service_release_fd_store(s);
|
||||
+
|
||||
/* Get rid of the IPC bits of the user */
|
||||
unit_unref_uid_gid(UNIT(s), true);
|
||||
|
||||
@@ -2449,7 +2466,7 @@ static int service_start(Unit *u) {
|
||||
if (s->state == SERVICE_AUTO_RESTART)
|
||||
return -EAGAIN;
|
||||
|
||||
- assert(IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED));
|
||||
+ assert(IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_DEAD_RESOURCES_PINNED));
|
||||
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
@@ -2501,7 +2518,7 @@ static int service_stop(Unit *u) {
|
||||
|
||||
/* A restart will be scheduled or is in progress. */
|
||||
if (s->state == SERVICE_AUTO_RESTART) {
|
||||
- service_set_state(s, SERVICE_DEAD);
|
||||
+ service_set_state(s, service_determine_dead_state(s));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3312,6 +3332,7 @@ static void service_notify_cgroup_empty_event(Unit *u) {
|
||||
* up the cgroup earlier and should do it now. */
|
||||
case SERVICE_DEAD:
|
||||
case SERVICE_FAILED:
|
||||
+ case SERVICE_DEAD_RESOURCES_PINNED:
|
||||
unit_prune_cgroup(u);
|
||||
break;
|
||||
|
||||
@@ -4332,7 +4353,7 @@ int service_set_socket_fd(
|
||||
|
||||
assert(!s->socket_peer);
|
||||
|
||||
- if (s->state != SERVICE_DEAD)
|
||||
+ if (!IN_SET(s->state, SERVICE_DEAD, SERVICE_DEAD_RESOURCES_PINNED))
|
||||
return -EAGAIN;
|
||||
|
||||
if (getpeername_pretty(fd, true, &peer_text) >= 0) {
|
||||
@@ -4369,7 +4390,7 @@ static void service_reset_failed(Unit *u) {
|
||||
assert(s);
|
||||
|
||||
if (s->state == SERVICE_FAILED)
|
||||
- service_set_state(s, SERVICE_DEAD);
|
||||
+ service_set_state(s, service_determine_dead_state(s));
|
||||
|
||||
s->result = SERVICE_SUCCESS;
|
||||
s->reload_result = SERVICE_SUCCESS;
|
||||
@@ -4531,14 +4552,19 @@ static void service_release_resources(Unit *u) {
|
||||
/* Don't release resources if this is a transitionary failed/dead state
|
||||
* (i.e. SERVICE_DEAD_BEFORE_AUTO_RESTART/SERVICE_FAILED_BEFORE_AUTO_RESTART), insist on a permanent
|
||||
* failure state. */
|
||||
- if (!IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED))
|
||||
+ if (!IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_DEAD_RESOURCES_PINNED))
|
||||
return;
|
||||
|
||||
log_unit_debug(u, "Releasing resources...");
|
||||
|
||||
service_close_socket_fd(s);
|
||||
service_release_stdio_fd(s);
|
||||
- service_release_fd_store(s);
|
||||
+
|
||||
+ if (s->fd_store_preserve_mode != EXEC_PRESERVE_YES)
|
||||
+ service_release_fd_store(s);
|
||||
+
|
||||
+ if (s->state == SERVICE_DEAD_RESOURCES_PINNED && !s->fd_store)
|
||||
+ service_set_state(s, SERVICE_DEAD);
|
||||
}
|
||||
|
||||
static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
|
||||
diff --git a/src/core/service.h b/src/core/service.h
|
||||
index 2e803a3..04bdcb2 100644
|
||||
--- a/src/core/service.h
|
||||
+++ b/src/core/service.h
|
||||
@@ -194,6 +194,7 @@ struct Service {
|
||||
size_t n_fd_store;
|
||||
unsigned n_fd_store_max;
|
||||
unsigned n_keep_fd_store;
|
||||
+ ExecPreserveMode fd_store_preserve_mode;
|
||||
|
||||
char *usb_function_descriptors;
|
||||
char *usb_function_strings;
|
||||
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
|
||||
index d3a5b25..b944cd0 100644
|
||||
--- a/src/shared/bus-unit-util.c
|
||||
+++ b/src/shared/bus-unit-util.c
|
||||
@@ -1999,7 +1999,8 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con
|
||||
"USBFunctionStrings",
|
||||
"OOMPolicy",
|
||||
"TimeoutStartFailureMode",
|
||||
- "TimeoutStopFailureMode"))
|
||||
+ "TimeoutStopFailureMode",
|
||||
+ "FileDescriptorStorePreserve"))
|
||||
return bus_append_string(m, field, eq);
|
||||
|
||||
if (STR_IN_SET(field, "PermissionsStartOnly",
|
||||
diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service
|
||||
index de7d2c7..0509c36 100644
|
||||
--- a/test/fuzz/fuzz-unit-file/directives.service
|
||||
+++ b/test/fuzz/fuzz-unit-file/directives.service
|
||||
@@ -163,6 +163,7 @@ ExecStopPost=
|
||||
ExtensionImages=
|
||||
FailureAction=
|
||||
FileDescriptorStoreMax=
|
||||
+FileDescriptorStorePreserve=
|
||||
FinalKillSignal=
|
||||
Group=
|
||||
GuessMainPID=
|
||||
--
|
||||
2.33.0
|
||||
|
||||
283
backport-service-allow-freeing-the-fdstore-via-cleaning.patch
Normal file
283
backport-service-allow-freeing-the-fdstore-via-cleaning.patch
Normal file
@ -0,0 +1,283 @@
|
||||
From 4fb8f1e88322b94b0fa051d3c6fd19cac0227aaa Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 29 Mar 2023 22:10:01 +0200
|
||||
Subject: [PATCH] service: allow freeing the fdstore via cleaning
|
||||
|
||||
Now that we have a potentially pinned fdstore let's add a concept for
|
||||
cleaning it explicitly on user requested. Let's expose this via
|
||||
"systemctl clean", i.e. the same way as user directories are cleaned.
|
||||
|
||||
Conflict:Adaptation context.
|
||||
Reference:https://github.com/systemd/systemd/commit/4fb8f1e88322b94b0fa051d3c6fd19cac0227aaa
|
||||
|
||||
---
|
||||
man/systemctl.xml | 28 +++++++++++-------
|
||||
src/core/dbus-unit.c | 21 ++++++-------
|
||||
src/core/execute.c | 17 +++++++++++
|
||||
src/core/execute.h | 5 +++-
|
||||
src/core/service.c | 36 ++++++++++++++++++++---
|
||||
src/core/timer.c | 1 +
|
||||
src/systemctl/systemctl-clean-or-freeze.c | 2 +-
|
||||
src/systemctl/systemctl.c | 3 +-
|
||||
8 files changed, 86 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/man/systemctl.xml b/man/systemctl.xml
|
||||
index 8402b95..a2cc54c 100644
|
||||
--- a/man/systemctl.xml
|
||||
+++ b/man/systemctl.xml
|
||||
@@ -484,12 +484,16 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
<varname>StateDirectory=</varname>, <varname>CacheDirectory=</varname>,
|
||||
<varname>LogsDirectory=</varname> and <varname>RuntimeDirectory=</varname>, see
|
||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
- for details. For timer units this may be used to clear out the persistent timestamp data if
|
||||
+ for details. It may also be used to clear the file decriptor store as enabled via
|
||||
+ <varname>FileDescriptorStoreMax=</varname>, see
|
||||
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
+ for details. For timer units this may be used to clear out the persistent timestamp data if
|
||||
<varname>Persistent=</varname> is used and <option>--what=state</option> is selected, see
|
||||
<citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>. This
|
||||
command only applies to units that use either of these settings. If <option>--what=</option> is
|
||||
- not specified, both the cache and runtime data are removed (as these two types of data are
|
||||
- generally redundant and reproducible on the next invocation of the unit).</para>
|
||||
+ not specified, the cache and runtime data as well as the file descriptor store are removed (as
|
||||
+ these three types of resources are generally redundant and reproducible on the next invocation of
|
||||
+ the unit). Note that the specified units must be stopped to invoke this operation.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
@@ -2076,13 +2080,17 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
|
||||
<listitem>
|
||||
<para>Select what type of per-unit resources to remove when the <command>clean</command> command is
|
||||
- invoked, see below. Takes one of <constant>configuration</constant>, <constant>state</constant>,
|
||||
- <constant>cache</constant>, <constant>logs</constant>, <constant>runtime</constant> to select the
|
||||
- type of resource. This option may be specified more than once, in which case all specified resource
|
||||
- types are removed. Also accepts the special value <constant>all</constant> as a shortcut for
|
||||
- specifying all five resource types. If this option is not specified defaults to the combination of
|
||||
- <constant>cache</constant> and <constant>runtime</constant>, i.e. the two kinds of resources that
|
||||
- are generally considered to be redundant and can be reconstructed on next invocation.</para>
|
||||
+ invoked, see above. Takes one of <constant>configuration</constant>, <constant>state</constant>,
|
||||
+ <constant>cache</constant>, <constant>logs</constant>, <constant>runtime</constant>,
|
||||
+ <constant>fdstore</constant> to select the type of resource. This option may be specified more than
|
||||
+ once, in which case all specified resource types are removed. Also accepts the special value
|
||||
+ <constant>all</constant> as a shortcut for specifying all six resource types. If this option is not
|
||||
+ specified defaults to the combination of <constant>cache</constant>, <constant>runtime</constant>
|
||||
+ and <constant>fdstore</constant>, i.e. the three kinds of resources that are generally considered
|
||||
+ to be redundant and can be reconstructed on next invocation. Note that the explicit removal of the
|
||||
+ <constant>fdstore</constant> resource type is only useful if the
|
||||
+ <varname>FileDescriptorStorePreserve=</varname> option is enabled, since the file descriptor store
|
||||
+ is otherwise cleaned automatically when the unit is stopped.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
|
||||
index 24e4d25..eefb08e 100644
|
||||
--- a/src/core/dbus-unit.c
|
||||
+++ b/src/core/dbus-unit.c
|
||||
@@ -91,6 +91,12 @@ static int property_get_can_clean(
|
||||
return r;
|
||||
}
|
||||
|
||||
+ if (FLAGS_SET(mask, EXEC_CLEAN_FDSTORE)) {
|
||||
+ r = sd_bus_message_append(reply, "s", "fdstore");
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
@@ -684,6 +690,7 @@ int bus_unit_method_clean(sd_bus_message *message, void *userdata, sd_bus_error
|
||||
return r;
|
||||
|
||||
for (;;) {
|
||||
+ ExecCleanMask m;
|
||||
const char *i;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &i);
|
||||
@@ -692,17 +699,11 @@ int bus_unit_method_clean(sd_bus_message *message, void *userdata, sd_bus_error
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
- if (streq(i, "all"))
|
||||
- mask |= EXEC_CLEAN_ALL;
|
||||
- else {
|
||||
- ExecDirectoryType t;
|
||||
-
|
||||
- t = exec_resource_type_from_string(i);
|
||||
- if (t < 0)
|
||||
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid resource type: %s", i);
|
||||
+ m = exec_clean_mask_from_string(i);
|
||||
+ if (m < 0)
|
||||
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid resource type: %s", i);
|
||||
|
||||
- mask |= 1U << t;
|
||||
- }
|
||||
+ mask |= m;
|
||||
}
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
diff --git a/src/core/execute.c b/src/core/execute.c
|
||||
index 9185a6f..e4c9e94 100644
|
||||
--- a/src/core/execute.c
|
||||
+++ b/src/core/execute.c
|
||||
@@ -6584,6 +6584,23 @@ ExecSetCredential *exec_set_credential_free(ExecSetCredential *sc) {
|
||||
return mfree(sc);
|
||||
}
|
||||
|
||||
+ExecCleanMask exec_clean_mask_from_string(const char *s) {
|
||||
+ ExecDirectoryType t;
|
||||
+
|
||||
+ assert(s);
|
||||
+
|
||||
+ if (streq(s, "all"))
|
||||
+ return EXEC_CLEAN_ALL;
|
||||
+ if (streq(s, "fdstore"))
|
||||
+ return EXEC_CLEAN_FDSTORE;
|
||||
+
|
||||
+ t = exec_resource_type_from_string(s);
|
||||
+ if (t < 0)
|
||||
+ return (ExecCleanMask) t;
|
||||
+
|
||||
+ return 1U << t;
|
||||
+}
|
||||
+
|
||||
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(exec_set_credential_hash_ops, char, string_hash_func, string_compare_func, ExecSetCredential, exec_set_credential_free);
|
||||
|
||||
static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
|
||||
diff --git a/src/core/execute.h b/src/core/execute.h
|
||||
index f1f0ee4..fd83a8c 100644
|
||||
--- a/src/core/execute.h
|
||||
+++ b/src/core/execute.h
|
||||
@@ -145,8 +145,9 @@ typedef enum ExecCleanMask {
|
||||
EXEC_CLEAN_CACHE = 1U << EXEC_DIRECTORY_CACHE,
|
||||
EXEC_CLEAN_LOGS = 1U << EXEC_DIRECTORY_LOGS,
|
||||
EXEC_CLEAN_CONFIGURATION = 1U << EXEC_DIRECTORY_CONFIGURATION,
|
||||
+ EXEC_CLEAN_FDSTORE = 1U << _EXEC_DIRECTORY_TYPE_MAX,
|
||||
EXEC_CLEAN_NONE = 0,
|
||||
- EXEC_CLEAN_ALL = (1U << _EXEC_DIRECTORY_TYPE_MAX) - 1,
|
||||
+ EXEC_CLEAN_ALL = (1U << (_EXEC_DIRECTORY_TYPE_MAX+1)) - 1,
|
||||
_EXEC_CLEAN_MASK_INVALID = -EINVAL,
|
||||
} ExecCleanMask;
|
||||
|
||||
@@ -459,6 +460,8 @@ bool exec_context_get_cpu_affinity_from_numa(const ExecContext *c);
|
||||
ExecSetCredential *exec_set_credential_free(ExecSetCredential *sc);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(ExecSetCredential*, exec_set_credential_free);
|
||||
|
||||
+ExecCleanMask exec_clean_mask_from_string(const char *s);
|
||||
+
|
||||
extern const struct hash_ops exec_set_credential_hash_ops;
|
||||
|
||||
const char* exec_output_to_string(ExecOutput i) _const_;
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index 25aec40..d52ffe7 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -4500,22 +4500,39 @@ static int service_exit_status(Unit *u) {
|
||||
|
||||
static int service_clean(Unit *u, ExecCleanMask mask) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
+ bool may_clean_fdstore = false;
|
||||
Service *s = SERVICE(u);
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(mask != 0);
|
||||
|
||||
- if (s->state != SERVICE_DEAD)
|
||||
+ if (!IN_SET(s->state, SERVICE_DEAD, SERVICE_DEAD_RESOURCES_PINNED))
|
||||
return -EBUSY;
|
||||
|
||||
+ /* Determine if there's anything we could potentially clean */
|
||||
r = exec_context_get_clean_directories(&s->exec_context, u->manager->prefix, mask, &l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- if (strv_isempty(l))
|
||||
- return -EUNATCH;
|
||||
+ if (mask & EXEC_CLEAN_FDSTORE)
|
||||
+ may_clean_fdstore = s->n_fd_store > 0 || s->n_fd_store_max > 0;
|
||||
+
|
||||
+ if (strv_isempty(l) && !may_clean_fdstore)
|
||||
+ return -EUNATCH; /* Nothing to potentially clean */
|
||||
+
|
||||
+ /* Let's clean the stuff we can clean quickly */
|
||||
+ if (may_clean_fdstore)
|
||||
+ service_release_fd_store(s);
|
||||
+
|
||||
+ /* If we are done, leave quickly */
|
||||
+ if (strv_isempty(l)) {
|
||||
+ if (s->state == SERVICE_DEAD_RESOURCES_PINNED && !s->fd_store)
|
||||
+ service_set_state(s, SERVICE_DEAD);
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
+ /* We need to clean disk stuff. This is slow, hence do it out of process, and change state */
|
||||
service_unwatch_control_pid(s);
|
||||
s->clean_result = SERVICE_SUCCESS;
|
||||
s->control_command = NULL;
|
||||
@@ -4542,10 +4559,21 @@ fail:
|
||||
|
||||
static int service_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
Service *s = SERVICE(u);
|
||||
+ ExecCleanMask mask = 0;
|
||||
+ int r;
|
||||
|
||||
assert(s);
|
||||
+ assert(ret);
|
||||
+
|
||||
+ r = exec_context_get_clean_mask(&s->exec_context, &mask);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
|
||||
- return exec_context_get_clean_mask(&s->exec_context, ret);
|
||||
+ if (s->n_fd_store_max > 0)
|
||||
+ mask |= EXEC_CLEAN_FDSTORE;
|
||||
+
|
||||
+ *ret = mask;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static const char *service_finished_job(Unit *u, JobType t, JobResult result) {
|
||||
diff --git a/src/core/timer.c b/src/core/timer.c
|
||||
index 77c8ce4..b038004 100644
|
||||
--- a/src/core/timer.c
|
||||
+++ b/src/core/timer.c
|
||||
@@ -891,6 +891,7 @@ static int timer_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
Timer *t = TIMER(u);
|
||||
|
||||
assert(t);
|
||||
+ assert(ret);
|
||||
|
||||
*ret = t->persistent ? EXEC_CLEAN_STATE : 0;
|
||||
return 0;
|
||||
diff --git a/src/systemctl/systemctl-clean-or-freeze.c b/src/systemctl/systemctl-clean-or-freeze.c
|
||||
index eca3a6d..0fe9441 100644
|
||||
--- a/src/systemctl/systemctl-clean-or-freeze.c
|
||||
+++ b/src/systemctl/systemctl-clean-or-freeze.c
|
||||
@@ -22,7 +22,7 @@ int clean_or_freeze_unit(int argc, char *argv[], void *userdata) {
|
||||
polkit_agent_open_maybe();
|
||||
|
||||
if (!arg_clean_what) {
|
||||
- arg_clean_what = strv_new("cache", "runtime");
|
||||
+ arg_clean_what = strv_new("cache", "runtime", "fdstore");
|
||||
if (!arg_clean_what)
|
||||
return log_oom();
|
||||
}
|
||||
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
|
||||
index 2f6f581..887bb47 100644
|
||||
--- a/src/systemctl/systemctl.c
|
||||
+++ b/src/systemctl/systemctl.c
|
||||
@@ -870,7 +870,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
|
||||
"state\n"
|
||||
"cache\n"
|
||||
"logs\n"
|
||||
- "configuration");
|
||||
+ "configuration\n"
|
||||
+ "fdstore");
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.33.0
|
||||
|
||||
90
backport-service-close-fdstore-asynchronously.patch
Normal file
90
backport-service-close-fdstore-asynchronously.patch
Normal file
@ -0,0 +1,90 @@
|
||||
From 99620f457ed0886852ba18c9093b59767299121c Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 4 Apr 2023 12:17:16 +0200
|
||||
Subject: [PATCH] service: close fdstore asynchronously
|
||||
|
||||
The file descriptors we keep in the fdstore might be basically anything,
|
||||
let's clean it up with our asynchronous closing feature, to not
|
||||
deadlock on close().
|
||||
|
||||
(Let's also do the same for stdin/stdout/stderr fds, since they might
|
||||
point to network services these days.)
|
||||
|
||||
Conflict:fd adaptation, the actual code function does not change.
|
||||
Reference:https://github.com/systemd/systemd/commit/99620f457ed0886852ba18c9093b59767299121c
|
||||
|
||||
---
|
||||
TODO | 2 --
|
||||
src/core/service.c | 15 ++++++++-------
|
||||
2 files changed, 8 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/TODO b/TODO
|
||||
index 75f885c..27b85ea 100644
|
||||
--- a/TODO
|
||||
+++ b/TODO
|
||||
@@ -531,8 +531,6 @@ Features:
|
||||
* maybe rework get_user_creds() to query the user database if $SHELL is used
|
||||
for root, but only then.
|
||||
|
||||
-* be stricter with fds we receive for the fdstore: close them asynchronously
|
||||
-
|
||||
* calenderspec: add support for week numbers and day numbers within a
|
||||
year. This would allow us to define "bi-weekly" triggers safely.
|
||||
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index d52ffe7..1b18a83 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -334,7 +334,7 @@ static void service_fd_store_unlink(ServiceFDStore *fs) {
|
||||
sd_event_source_disable_unref(fs->event_source);
|
||||
|
||||
free(fs->fdname);
|
||||
- safe_close(fs->fd);
|
||||
+ asynchronous_close(fs->fd);
|
||||
free(fs);
|
||||
}
|
||||
|
||||
@@ -360,9 +360,9 @@ static void service_release_stdio_fd(Service *s) {
|
||||
|
||||
log_unit_debug(UNIT(s), "Releasing stdin/stdout/stderr file descriptors.");
|
||||
|
||||
- s->stdin_fd = safe_close(s->stdin_fd);
|
||||
- s->stdout_fd = safe_close(s->stdout_fd);
|
||||
- s->stderr_fd = safe_close(s->stderr_fd);
|
||||
+ s->stdin_fd = asynchronous_close(s->stdin_fd);
|
||||
+ s->stdout_fd = asynchronous_close(s->stdout_fd);
|
||||
+ s->stderr_fd = asynchronous_close(s->stderr_fd);
|
||||
}
|
||||
static void service_done(Unit *u) {
|
||||
Service *s = SERVICE(u);
|
||||
@@ -448,7 +448,7 @@ static int service_add_fd_store(Service *s, int fd, const char *name, bool do_po
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0) {
|
||||
- safe_close(fd);
|
||||
+ asynchronous_close(fd);
|
||||
return 0; /* fd already included */
|
||||
}
|
||||
}
|
||||
@@ -491,7 +491,7 @@ static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name, bo
|
||||
assert(s);
|
||||
|
||||
while (fdset_size(fds) > 0) {
|
||||
- _cleanup_close_ int fd = -1;
|
||||
+ _cleanup_(asynchronous_closep) int fd = -EBADF;
|
||||
|
||||
fd = fdset_steal_first(fds);
|
||||
if (fd < 0)
|
||||
@@ -506,7 +506,8 @@ static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name, bo
|
||||
return log_unit_error_errno(UNIT(s), r, "Failed to add fd to store: %m");
|
||||
if (r > 0)
|
||||
log_unit_debug(UNIT(s), "Added fd %u (%s) to fd store.", fd, strna(name));
|
||||
- fd = -1;
|
||||
+
|
||||
+ TAKE_FD(fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
--
|
||||
2.33.0
|
||||
|
||||
31
backport-service-drop-redundant-unit_ref_unset-call.patch
Normal file
31
backport-service-drop-redundant-unit_ref_unset-call.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From d53bda316be6ba226788b40e101a3bff5aa75a5f Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 29 Mar 2023 22:04:26 +0200
|
||||
Subject: [PATCH] service: drop redundant unit_ref_unset() call
|
||||
|
||||
The immediately preceeding service_close_socket_fd() call does that
|
||||
internally anyway. No need to do this again right after.
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd/commit/d53bda316be6ba226788b40e101a3bff5aa75a5f
|
||||
|
||||
---
|
||||
src/core/service.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index d73feb363e..c4a7be890d 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -452,8 +452,6 @@ static void service_done(Unit *u) {
|
||||
|
||||
service_close_socket_fd(s);
|
||||
|
||||
- unit_ref_unset(&s->accept_socket);
|
||||
-
|
||||
service_stop_watchdog(s);
|
||||
|
||||
s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,286 @@
|
||||
From 6ac62d61db737b01ad3776a7688d8a4c57b3f7d9 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 29 Mar 2023 21:52:41 +0200
|
||||
Subject: [PATCH] service: release resources from a seperate queue, not
|
||||
unit_check_gc()
|
||||
|
||||
The per-unit-type release_resources() hook (most prominent use: to
|
||||
release a service unit's fdstore once a unit is entirely dead and has no
|
||||
jobs more) was currently invoked as part of unit_check_gc(), whose
|
||||
primary purpose is to determine if a unit should be GC'ed. This was
|
||||
always a bit ugly, as release_resources() changes state of the unit,
|
||||
while unit_check_gc() is otherwise (and was before release_resources()
|
||||
was added) a "passive" function that just checks for a couple of
|
||||
conditions.
|
||||
|
||||
unit_check_gc() is called at various places, including when we wonder if
|
||||
we should add a unit to the gc queue, and then again when we take it out
|
||||
of the gc queue to dtermine whether to really gc it now. The fact that
|
||||
these checks have side effects so far wasn't too problematic, as the
|
||||
state changes (primarily: that services would empty their fdstores) were
|
||||
relatively limited and scope.
|
||||
|
||||
A later patch in this series is supposed to extend the service state
|
||||
engine with a separate state distinct from SERVICE_DEAD that is very
|
||||
much like it but indicates that the service still has active resources
|
||||
(specifically the fdstore). For cases like that the releasing of the
|
||||
fdstore would result in state changes (as we'd then return to a classic
|
||||
SERVICE_DEAD state). And this is where the fact that the
|
||||
release_resources() is called as side-effect becomes problematic: it
|
||||
would mean that unit state changes would instantly propagate to state
|
||||
changes elsewhere, though we usually want this to be done through the
|
||||
run queue for coalescing and avoidance of recursion.
|
||||
|
||||
Hence, let's clean this up: let's move the release_resources() logic
|
||||
into a queue of its own, and then enqueue items into it from the general
|
||||
state change notification handle in unit_notify().
|
||||
|
||||
Conflict:Adapt to context
|
||||
Reference:https://github.com/systemd/systemd/commit/6ac62d61db737b01ad3776a7688d8a4c57b3f7d9
|
||||
|
||||
---
|
||||
src/core/manager.c | 23 ++++++++++++++
|
||||
src/core/manager.h | 3 ++
|
||||
src/core/unit.c | 75 +++++++++++++++++++++++++++++++++++-----------
|
||||
src/core/unit.h | 7 +++++
|
||||
4 files changed, 91 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/src/core/manager.c b/src/core/manager.c
|
||||
index 3c83c82..3245acd 100644
|
||||
--- a/src/core/manager.c
|
||||
+++ b/src/core/manager.c
|
||||
@@ -1108,6 +1108,26 @@ static unsigned manager_dispatch_cleanup_queue(Manager *m) {
|
||||
return n;
|
||||
}
|
||||
|
||||
+static unsigned manager_dispatch_release_resources_queue(Manager *m) {
|
||||
+ unsigned n = 0;
|
||||
+ Unit *u;
|
||||
+
|
||||
+ assert(m);
|
||||
+
|
||||
+ while ((u = m->release_resources_queue)) {
|
||||
+ assert(u->in_release_resources_queue);
|
||||
+
|
||||
+ LIST_REMOVE(release_resources_queue, m->release_resources_queue, u);
|
||||
+ u->in_release_resources_queue = false;
|
||||
+
|
||||
+ n++;
|
||||
+
|
||||
+ unit_release_resources(u);
|
||||
+ }
|
||||
+
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
enum {
|
||||
GC_OFFSET_IN_PATH, /* This one is on the path we were traveling */
|
||||
GC_OFFSET_UNSURE, /* No clue */
|
||||
@@ -2966,6 +2986,9 @@ int manager_loop(Manager *m) {
|
||||
if (manager_dispatch_stop_when_unneeded_queue(m) > 0)
|
||||
continue;
|
||||
|
||||
+ if (manager_dispatch_release_resources_queue(m) > 0)
|
||||
+ continue;
|
||||
+
|
||||
if (manager_dispatch_dbus_queue(m) > 0)
|
||||
continue;
|
||||
|
||||
diff --git a/src/core/manager.h b/src/core/manager.h
|
||||
index 226cfc9..f53e5d5 100644
|
||||
--- a/src/core/manager.h
|
||||
+++ b/src/core/manager.h
|
||||
@@ -193,6 +193,9 @@ struct Manager {
|
||||
/* Units that have BindsTo= another unit, and might need to be shutdown because the bound unit is not active. */
|
||||
LIST_HEAD(Unit, stop_when_bound_queue);
|
||||
|
||||
+ /* Units that have resources open, and where it might be good to check if they can be released now */
|
||||
+ LIST_HEAD(Unit, release_resources_queue);
|
||||
+
|
||||
sd_event *event;
|
||||
|
||||
/* This maps PIDs we care about to units that are interested in. We allow multiple units to be interested in
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index d75c8a9..af225e2 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -370,18 +370,39 @@ int unit_set_description(Unit *u, const char *description) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+void unit_release_resources(Unit *u) {
|
||||
+ UnitActiveState state;
|
||||
+
|
||||
+ assert(u);
|
||||
+
|
||||
+ if (u->job || u->nop_job)
|
||||
+ return;
|
||||
+
|
||||
+ if (u->perpetual)
|
||||
+ return;
|
||||
+
|
||||
+ state = unit_active_state(u);
|
||||
+ if (!IN_SET(state, UNIT_INACTIVE, UNIT_FAILED))
|
||||
+ return;
|
||||
+
|
||||
+ if (unit_will_restart(u))
|
||||
+ return;
|
||||
+
|
||||
+ if (UNIT_VTABLE(u)->release_resources)
|
||||
+ UNIT_VTABLE(u)->release_resources(u);
|
||||
+}
|
||||
+
|
||||
bool unit_may_gc(Unit *u) {
|
||||
UnitActiveState state;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
|
||||
- /* Checks whether the unit is ready to be unloaded for garbage collection.
|
||||
- * Returns true when the unit may be collected, and false if there's some
|
||||
- * reason to keep it loaded.
|
||||
+ /* Checks whether the unit is ready to be unloaded for garbage collection. Returns true when the
|
||||
+ * unit may be collected, and false if there's some reason to keep it loaded.
|
||||
*
|
||||
- * References from other units are *not* checked here. Instead, this is done
|
||||
- * in unit_gc_sweep(), but using markers to properly collect dependency loops.
|
||||
+ * References from other units are *not* checked here. Instead, this is done in unit_gc_sweep(), but
|
||||
+ * using markers to properly collect dependency loops.
|
||||
*/
|
||||
|
||||
if (u->job)
|
||||
@@ -390,20 +411,16 @@ bool unit_may_gc(Unit *u) {
|
||||
if (u->nop_job)
|
||||
return false;
|
||||
|
||||
- state = unit_active_state(u);
|
||||
-
|
||||
- /* If the unit is inactive and failed and no job is queued for it, then release its runtime resources */
|
||||
- if (UNIT_IS_INACTIVE_OR_FAILED(state) &&
|
||||
- UNIT_VTABLE(u)->release_resources)
|
||||
- UNIT_VTABLE(u)->release_resources(u);
|
||||
-
|
||||
if (u->perpetual)
|
||||
return false;
|
||||
|
||||
if (sd_bus_track_count(u->bus_track) > 0)
|
||||
return false;
|
||||
|
||||
- /* But we keep the unit object around for longer when it is referenced or configured to not be gc'ed */
|
||||
+ state = unit_active_state(u);
|
||||
+
|
||||
+ /* But we keep the unit object around for longer when it is referenced or configured to not be
|
||||
+ * gc'ed */
|
||||
switch (u->collect_mode) {
|
||||
|
||||
case COLLECT_INACTIVE:
|
||||
@@ -433,10 +450,10 @@ bool unit_may_gc(Unit *u) {
|
||||
return false;
|
||||
}
|
||||
|
||||
- if (UNIT_VTABLE(u)->may_gc && !UNIT_VTABLE(u)->may_gc(u))
|
||||
- return false;
|
||||
+ if (!UNIT_VTABLE(u)->may_gc)
|
||||
+ return true;
|
||||
|
||||
- return true;
|
||||
+ return UNIT_VTABLE(u)->may_gc(u);
|
||||
}
|
||||
|
||||
void unit_add_to_load_queue(Unit *u) {
|
||||
@@ -540,6 +557,25 @@ void unit_submit_to_stop_when_bound_queue(Unit *u) {
|
||||
u->in_stop_when_bound_queue = true;
|
||||
}
|
||||
|
||||
+void unit_submit_to_release_resources_queue(Unit *u) {
|
||||
+ assert(u);
|
||||
+
|
||||
+ if (u->in_release_resources_queue)
|
||||
+ return;
|
||||
+
|
||||
+ if (u->job || u->nop_job)
|
||||
+ return;
|
||||
+
|
||||
+ if (u->perpetual)
|
||||
+ return;
|
||||
+
|
||||
+ if (!UNIT_VTABLE(u)->release_resources)
|
||||
+ return;
|
||||
+
|
||||
+ LIST_PREPEND(release_resources_queue, u->manager->release_resources_queue, u);
|
||||
+ u->in_release_resources_queue = true;
|
||||
+}
|
||||
+
|
||||
static void unit_clear_dependencies(Unit *u) {
|
||||
assert(u);
|
||||
|
||||
@@ -761,6 +797,9 @@ Unit* unit_free(Unit *u) {
|
||||
if (u->in_stop_when_bound_queue)
|
||||
LIST_REMOVE(stop_when_bound_queue, u->manager->stop_when_bound_queue, u);
|
||||
|
||||
+ if (u->in_release_resources_queue)
|
||||
+ LIST_REMOVE(release_resources_queue, u->manager->release_resources_queue, u);
|
||||
+
|
||||
bpf_firewall_close(u);
|
||||
|
||||
hashmap_free(u->bpf_foreign_by_key);
|
||||
@@ -2494,7 +2533,6 @@ static bool unit_process_job(Job *j, UnitActiveState ns, UnitNotifyFlags flags)
|
||||
assert(j);
|
||||
|
||||
if (j->state == JOB_WAITING)
|
||||
-
|
||||
/* So we reached a different state for this job. Let's see if we can run it now if it failed previously
|
||||
* due to EAGAIN. */
|
||||
job_add_to_run_queue(j);
|
||||
@@ -2698,6 +2736,9 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag
|
||||
|
||||
/* Maybe the unit should be GC'ed now? */
|
||||
unit_add_to_gc_queue(u);
|
||||
+
|
||||
+ /* Maybe we can release some resources now? */
|
||||
+ unit_submit_to_release_resources_queue(u);
|
||||
}
|
||||
|
||||
if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) {
|
||||
diff --git a/src/core/unit.h b/src/core/unit.h
|
||||
index 6485858..16c65d9 100644
|
||||
--- a/src/core/unit.h
|
||||
+++ b/src/core/unit.h
|
||||
@@ -241,6 +241,9 @@ typedef struct Unit {
|
||||
/* Queue of units that have a BindTo= dependency on some other unit, and should possibly be shut down */
|
||||
LIST_FIELDS(Unit, stop_when_bound_queue);
|
||||
|
||||
+ /* Queue of units that should be checked if they can release resources now */
|
||||
+ LIST_FIELDS(Unit, release_resources_queue);
|
||||
+
|
||||
/* PIDs we keep an eye on. Note that a unit might have many
|
||||
* more, but these are the ones we care enough about to
|
||||
* process SIGCHLD for */
|
||||
@@ -393,6 +396,7 @@ typedef struct Unit {
|
||||
bool in_stop_when_unneeded_queue:1;
|
||||
bool in_start_when_upheld_queue:1;
|
||||
bool in_stop_when_bound_queue:1;
|
||||
+ bool in_release_resources_queue:1;
|
||||
|
||||
bool sent_dbus_new_signal:1;
|
||||
|
||||
@@ -744,6 +748,8 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c);
|
||||
int unit_choose_id(Unit *u, const char *name);
|
||||
int unit_set_description(Unit *u, const char *description);
|
||||
|
||||
+void unit_release_resources(Unit *u);
|
||||
+
|
||||
bool unit_may_gc(Unit *u);
|
||||
|
||||
static inline bool unit_is_extrinsic(Unit *u) {
|
||||
@@ -759,6 +765,7 @@ void unit_add_to_target_deps_queue(Unit *u);
|
||||
void unit_submit_to_stop_when_unneeded_queue(Unit *u);
|
||||
void unit_submit_to_start_when_upheld_queue(Unit *u);
|
||||
void unit_submit_to_stop_when_bound_queue(Unit *u);
|
||||
+void unit_submit_to_release_resources_queue(Unit *u);
|
||||
|
||||
int unit_merge(Unit *u, Unit *other);
|
||||
int unit_merge_by_name(Unit *u, const char *other);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
From 81a1d6d6790ad6ae8ff63147dfab68e6835178c3 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 4 Apr 2023 15:51:07 +0200
|
||||
Subject: [PATCH] =?UTF-8?q?service:=20rename=20service=5Fclose=5Fsocket=5F?=
|
||||
=?UTF-8?q?fd()=20=E2=86=92=20service=5Frelease=5Fsocket=5Ffd()?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Just to match service_release_stdio_fd() and service_release_fd_store()
|
||||
in the name, since they do similar things.
|
||||
|
||||
This follows the concept that we "release" resources, and this is all
|
||||
generically wrapped in "service_release_resources()".
|
||||
|
||||
Conflict:Context Adaptation.
|
||||
Reference:https://github.com/systemd/systemd/commit/81a1d6d6790ad6ae8ff63147dfab68e6835178c3
|
||||
|
||||
---
|
||||
src/core/service.c | 9 ++++-----
|
||||
src/core/service.h | 2 +-
|
||||
src/core/socket.c | 2 +-
|
||||
3 files changed, 6 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index 9bd82fc..a7d5f3f 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -188,7 +188,7 @@ static int service_set_main_pid(Service *s, pid_t pid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
-void service_close_socket_fd(Service *s) {
|
||||
+void service_release_socket_fd(Service *s) {
|
||||
assert(s);
|
||||
|
||||
if (s->socket_fd < 0 && !UNIT_ISSET(s->accept_socket) && !s->socket_peer)
|
||||
@@ -399,8 +399,6 @@ static void service_done(Unit *u) {
|
||||
s->usb_function_descriptors = mfree(s->usb_function_descriptors);
|
||||
s->usb_function_strings = mfree(s->usb_function_strings);
|
||||
|
||||
- service_close_socket_fd(s);
|
||||
-
|
||||
service_stop_watchdog(s);
|
||||
|
||||
s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
|
||||
@@ -408,8 +406,9 @@ static void service_done(Unit *u) {
|
||||
|
||||
s->bus_name_pid_lookup_slot = sd_bus_slot_unref(s->bus_name_pid_lookup_slot);
|
||||
|
||||
- service_release_fd_store(s);
|
||||
+ service_release_socket_fd(s);
|
||||
service_release_stdio_fd(s);
|
||||
+ service_release_fd_store(s);
|
||||
}
|
||||
|
||||
static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *userdata) {
|
||||
@@ -4616,7 +4615,7 @@ static void service_release_resources(Unit *u) {
|
||||
|
||||
log_unit_debug(u, "Releasing resources...");
|
||||
|
||||
- service_close_socket_fd(s);
|
||||
+ service_release_socket_fd(s);
|
||||
service_release_stdio_fd(s);
|
||||
|
||||
if (s->fd_store_preserve_mode != EXEC_PRESERVE_YES)
|
||||
diff --git a/src/core/service.h b/src/core/service.h
|
||||
index 78a0f97..4a4ab8a 100644
|
||||
--- a/src/core/service.h
|
||||
+++ b/src/core/service.h
|
||||
@@ -221,7 +221,7 @@ static inline usec_t service_get_watchdog_usec(Service *s) {
|
||||
extern const UnitVTable service_vtable;
|
||||
|
||||
int service_set_socket_fd(Service *s, int fd, struct Socket *socket, struct SocketPeer *peer, bool selinux_context_net);
|
||||
-void service_close_socket_fd(Service *s);
|
||||
+void service_release_socket_fd(Service *s);
|
||||
|
||||
const char* service_restart_to_string(ServiceRestart i) _const_;
|
||||
ServiceRestart service_restart_from_string(const char *s) _pure_;
|
||||
diff --git a/src/core/socket.c b/src/core/socket.c
|
||||
index b1c534b..f61c302 100644
|
||||
--- a/src/core/socket.c
|
||||
+++ b/src/core/socket.c
|
||||
@@ -2426,7 +2426,7 @@ static void socket_enter_running(Socket *s, int cfd_in) {
|
||||
if (r < 0) {
|
||||
/* We failed to activate the new service, but it still exists. Let's make sure the
|
||||
* service closes and forgets the connection fd again, immediately. */
|
||||
- service_close_socket_fd(SERVICE(service));
|
||||
+ service_release_socket_fd(SERVICE(service));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
--
|
||||
2.33.0
|
||||
|
||||
137
backport-service-rework-how-we-release-resources.patch
Normal file
137
backport-service-rework-how-we-release-resources.patch
Normal file
@ -0,0 +1,137 @@
|
||||
From c25fac9a17b95271bb6f8d967d33c5a9aa9e4bc9 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 29 Mar 2023 22:06:39 +0200
|
||||
Subject: [PATCH] service: rework how we release resources
|
||||
|
||||
Let's normalize how we release service resources, i.e. the three types
|
||||
of fds we maintain for each service:
|
||||
|
||||
1. the fdstore
|
||||
2. the socket fd for per-connection socket activated services
|
||||
3. stdin/stdout/stderr
|
||||
|
||||
The generic service_release_resources() hook now calls into
|
||||
service_release_fd_store() + service_close_socket_fd()
|
||||
service_release_stdio_fd() one after the other, releasing them all for
|
||||
the generic "release_resources" infra of the unit lifecycle.
|
||||
|
||||
We do no longer close the socket fd from service_set_state(), moving
|
||||
this exclusively into service_release_resources(), so that all fds are
|
||||
closed the same way.
|
||||
|
||||
Conflict:Adaptation context. Deleted the features that are not introduced.
|
||||
Reference:https://github.com/systemd/systemd/commit/c25fac9a17b95271bb6f8d967d33c5a9aa9e4bc9
|
||||
|
||||
---
|
||||
src/core/service.c | 51 ++++++++++++++++++++++++++++++----------------
|
||||
1 file changed, 34 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index 7d823dd..af6360e 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -183,6 +183,11 @@ static int service_set_main_pid(Service *s, pid_t pid) {
|
||||
void service_close_socket_fd(Service *s) {
|
||||
assert(s);
|
||||
|
||||
+ if (s->socket_fd < 0 && !UNIT_ISSET(s->accept_socket) && !s->socket_peer)
|
||||
+ return;
|
||||
+
|
||||
+ log_unit_debug(UNIT(s), "Closing connection socket.");
|
||||
+
|
||||
/* Undo the effect of service_set_socket_fd(). */
|
||||
|
||||
s->socket_fd = asynchronous_close(s->socket_fd);
|
||||
@@ -331,30 +336,29 @@ static void service_release_fd_store(Service *s) {
|
||||
if (s->n_keep_fd_store > 0)
|
||||
return;
|
||||
|
||||
+ if (!s->fd_store)
|
||||
+ return;
|
||||
+
|
||||
log_unit_debug(UNIT(s), "Releasing all stored fds");
|
||||
+
|
||||
while (s->fd_store)
|
||||
service_fd_store_unlink(s->fd_store);
|
||||
|
||||
assert(s->n_fd_store == 0);
|
||||
}
|
||||
|
||||
-static void service_release_resources(Unit *u) {
|
||||
- Service *s = SERVICE(u);
|
||||
-
|
||||
+static void service_release_stdio_fd(Service *s) {
|
||||
assert(s);
|
||||
|
||||
- if (!s->fd_store && s->stdin_fd < 0 && s->stdout_fd < 0 && s->stderr_fd < 0)
|
||||
+ if (s->stdin_fd < 0 && s->stdout_fd < 0 && s->stdout_fd < 0)
|
||||
return;
|
||||
|
||||
- log_unit_debug(u, "Releasing resources.");
|
||||
+ log_unit_debug(UNIT(s), "Releasing stdin/stdout/stderr file descriptors.");
|
||||
|
||||
s->stdin_fd = safe_close(s->stdin_fd);
|
||||
s->stdout_fd = safe_close(s->stdout_fd);
|
||||
s->stderr_fd = safe_close(s->stderr_fd);
|
||||
-
|
||||
- service_release_fd_store(s);
|
||||
}
|
||||
-
|
||||
static void service_done(Unit *u) {
|
||||
Service *s = SERVICE(u);
|
||||
|
||||
@@ -399,7 +403,8 @@ static void service_done(Unit *u) {
|
||||
|
||||
s->bus_name_pid_lookup_slot = sd_bus_slot_unref(s->bus_name_pid_lookup_slot);
|
||||
|
||||
- service_release_resources(u);
|
||||
+ service_release_fd_store(s);
|
||||
+ service_release_stdio_fd(s);
|
||||
}
|
||||
|
||||
static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *userdata) {
|
||||
@@ -1101,14 +1106,6 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
unit_dequeue_rewatch_pids(UNIT(s));
|
||||
}
|
||||
|
||||
- if (!IN_SET(state,
|
||||
- SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
- SERVICE_RUNNING, SERVICE_RELOAD,
|
||||
- SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
- SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL) &&
|
||||
- !(state == SERVICE_DEAD && UNIT(s)->job))
|
||||
- service_close_socket_fd(s);
|
||||
-
|
||||
if (state != SERVICE_START)
|
||||
s->exec_fd_event_source = sd_event_source_disable_unref(s->exec_fd_event_source);
|
||||
|
||||
@@ -4524,6 +4521,26 @@ static int service_can_start(Unit *u) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static void service_release_resources(Unit *u) {
|
||||
+ Service *s = SERVICE(u);
|
||||
+ assert(s);
|
||||
+
|
||||
+ /* Invoked by the unit state engine, whenever it realizes that unit is dead and there's no job
|
||||
+ * anymore for it, and it hence is a good idea to release resources */
|
||||
+
|
||||
+ /* Don't release resources if this is a transitionary failed/dead state
|
||||
+ * (i.e. SERVICE_DEAD_BEFORE_AUTO_RESTART/SERVICE_FAILED_BEFORE_AUTO_RESTART), insist on a permanent
|
||||
+ * failure state. */
|
||||
+ if (!IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED))
|
||||
+ return;
|
||||
+
|
||||
+ log_unit_debug(u, "Releasing resources...");
|
||||
+
|
||||
+ service_close_socket_fd(s);
|
||||
+ service_release_stdio_fd(s);
|
||||
+ service_release_fd_store(s);
|
||||
+}
|
||||
+
|
||||
static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
|
||||
[SERVICE_RESTART_NO] = "no",
|
||||
[SERVICE_RESTART_ON_SUCCESS] = "on-success",
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,174 @@
|
||||
From 3fabebf45e268a0e1e8f9e7688b2428f8ee8a802 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 24 Nov 2021 23:50:07 +0100
|
||||
Subject: [PATCH] socket: always pass socket, fd and SocketPeer ownership to
|
||||
service together
|
||||
|
||||
Per-connection socket instances we currently maintain three fields
|
||||
related to the socket: a reference to the Socket unit, the connection fd,
|
||||
and a reference to the SocketPeer object that counts socket peers.
|
||||
|
||||
Let's synchronize their lifetime, i.e. always set them all three
|
||||
together or unset them together, so that their reference counters stay
|
||||
synchronous.
|
||||
|
||||
THis will in particuar ensure that we'll drop the SocketPeer reference
|
||||
whenever we leave an active state of the service unit, i.e. at the same
|
||||
time we close the fd for it.
|
||||
|
||||
Fixes: #20685
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd/commit/3fabebf45e268a0e1e8f9e7688b2428f8ee8a802
|
||||
|
||||
---
|
||||
src/core/service.c | 27 ++++++++++++++++++---------
|
||||
src/core/service.h | 9 +++++----
|
||||
src/core/socket.c | 4 +---
|
||||
3 files changed, 24 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/src/core/service.c b/src/core/service.c
|
||||
index 17c19a2c4a..49579f7998 100644
|
||||
--- a/src/core/service.c
|
||||
+++ b/src/core/service.c
|
||||
@@ -190,6 +190,8 @@ void service_close_socket_fd(Service *s) {
|
||||
socket_connection_unref(SOCKET(UNIT_DEREF(s->accept_socket)));
|
||||
unit_ref_unset(&s->accept_socket);
|
||||
}
|
||||
+
|
||||
+ s->socket_peer = socket_peer_unref(s->socket_peer);
|
||||
}
|
||||
|
||||
static void service_stop_watchdog(Service *s) {
|
||||
@@ -388,7 +390,6 @@ static void service_done(Unit *u) {
|
||||
s->usb_function_strings = mfree(s->usb_function_strings);
|
||||
|
||||
service_close_socket_fd(s);
|
||||
- s->peer = socket_peer_unref(s->peer);
|
||||
|
||||
unit_ref_unset(&s->accept_socket);
|
||||
|
||||
@@ -1237,8 +1238,8 @@ static int service_coldplug(Unit *u) {
|
||||
|
||||
/* Make a best-effort attempt at bumping the connection count */
|
||||
if (socket_acquire_peer(socket, s->socket_fd, &peer) > 0) {
|
||||
- socket_peer_unref(s->peer);
|
||||
- s->peer = peer;
|
||||
+ socket_peer_unref(s->socket_peer);
|
||||
+ s->socket_peer = peer;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4285,8 +4286,14 @@ static void service_bus_name_owner_change(Unit *u, const char *new_owner) {
|
||||
}
|
||||
}
|
||||
|
||||
-int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context_net) {
|
||||
- _cleanup_free_ char *peer = NULL;
|
||||
+int service_set_socket_fd(
|
||||
+ Service *s,
|
||||
+ int fd,
|
||||
+ Socket *sock,
|
||||
+ SocketPeer *peer,
|
||||
+ bool selinux_context_net) {
|
||||
+
|
||||
+ _cleanup_free_ char *peer_text = NULL;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
@@ -4301,22 +4308,23 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context
|
||||
if (s->socket_fd >= 0)
|
||||
return -EBUSY;
|
||||
|
||||
+ assert(!s->socket_peer);
|
||||
+
|
||||
if (s->state != SERVICE_DEAD)
|
||||
return -EAGAIN;
|
||||
|
||||
- if (getpeername_pretty(fd, true, &peer) >= 0) {
|
||||
+ if (getpeername_pretty(fd, true, &peer_text) >= 0) {
|
||||
|
||||
if (UNIT(s)->description) {
|
||||
_cleanup_free_ char *a = NULL;
|
||||
|
||||
- a = strjoin(UNIT(s)->description, " (", peer, ")");
|
||||
+ a = strjoin(UNIT(s)->description, " (", peer_text, ")");
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
|
||||
r = unit_set_description(UNIT(s), a);
|
||||
} else
|
||||
- r = unit_set_description(UNIT(s), peer);
|
||||
-
|
||||
+ r = unit_set_description(UNIT(s), peer_text);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -4326,6 +4334,7 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context
|
||||
return r;
|
||||
|
||||
s->socket_fd = fd;
|
||||
+ s->socket_peer = socket_peer_ref(peer);
|
||||
s->socket_fd_selinux_context_net = selinux_context_net;
|
||||
|
||||
unit_ref_set(&s->accept_socket, UNIT(s), UNIT(sock));
|
||||
diff --git a/src/core/service.h b/src/core/service.h
|
||||
index 70ce70fba5..778551d844 100644
|
||||
--- a/src/core/service.h
|
||||
+++ b/src/core/service.h
|
||||
@@ -157,8 +157,11 @@ struct Service {
|
||||
DynamicCreds dynamic_creds;
|
||||
|
||||
pid_t main_pid, control_pid;
|
||||
+
|
||||
+ /* if we are a socket activated service instance, store information of the connection/peer/socket */
|
||||
int socket_fd;
|
||||
- SocketPeer *peer;
|
||||
+ SocketPeer *socket_peer;
|
||||
+ UnitRef accept_socket;
|
||||
bool socket_fd_selinux_context_net;
|
||||
|
||||
bool permissions_start_only;
|
||||
@@ -186,8 +189,6 @@ struct Service {
|
||||
char *status_text;
|
||||
int status_errno;
|
||||
|
||||
- UnitRef accept_socket;
|
||||
-
|
||||
sd_event_source *timer_event_source;
|
||||
PathSpec *pid_file_pathspec;
|
||||
|
||||
@@ -226,7 +227,7 @@ static inline usec_t service_get_watchdog_usec(Service *s) {
|
||||
|
||||
extern const UnitVTable service_vtable;
|
||||
|
||||
-int service_set_socket_fd(Service *s, int fd, struct Socket *socket, bool selinux_context_net);
|
||||
+int service_set_socket_fd(Service *s, int fd, struct Socket *socket, struct SocketPeer *peer, bool selinux_context_net);
|
||||
void service_close_socket_fd(Service *s);
|
||||
|
||||
const char* service_restart_to_string(ServiceRestart i) _const_;
|
||||
diff --git a/src/core/socket.c b/src/core/socket.c
|
||||
index e6d168188a..d9db1edd3c 100644
|
||||
--- a/src/core/socket.c
|
||||
+++ b/src/core/socket.c
|
||||
@@ -2409,7 +2409,7 @@ static void socket_enter_running(Socket *s, int cfd_in) {
|
||||
|
||||
s->n_accepted++;
|
||||
|
||||
- r = service_set_socket_fd(SERVICE(service), cfd, s, s->selinux_context_from_net);
|
||||
+ r = service_set_socket_fd(SERVICE(service), cfd, s, p, s->selinux_context_from_net);
|
||||
if (ERRNO_IS_DISCONNECT(r))
|
||||
return;
|
||||
if (r < 0)
|
||||
@@ -2418,8 +2418,6 @@ static void socket_enter_running(Socket *s, int cfd_in) {
|
||||
TAKE_FD(cfd); /* We passed ownership of the fd to the service now. Forget it here. */
|
||||
s->n_connections++;
|
||||
|
||||
- SERVICE(service)->peer = TAKE_PTR(p); /* Pass ownership of the peer reference */
|
||||
-
|
||||
r = manager_add_job(UNIT(s)->manager, JOB_START, service, JOB_REPLACE, NULL, &error, NULL);
|
||||
if (r < 0) {
|
||||
/* We failed to activate the new service, but it still exists. Let's make sure the
|
||||
--
|
||||
2.33.0
|
||||
|
||||
94
backport-socket-various-modernizations.patch
Normal file
94
backport-socket-various-modernizations.patch
Normal file
@ -0,0 +1,94 @@
|
||||
From 000b61b980abba1a69d7a5e2a2a073930eca5e08 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Wed, 24 Nov 2021 23:53:10 +0100
|
||||
Subject: [PATCH] socket: various modernizations
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd/commit/000b61b980abba1a69d7a5e2a2a073930eca5e08
|
||||
|
||||
---
|
||||
src/core/socket.c | 25 +++++++++++++------------
|
||||
1 file changed, 13 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/src/core/socket.c b/src/core/socket.c
|
||||
index d9db1edd3c..6b5ec9d987 100644
|
||||
--- a/src/core/socket.c
|
||||
+++ b/src/core/socket.c
|
||||
@@ -463,10 +463,6 @@ static int socket_load(Unit *u) {
|
||||
assert(u);
|
||||
assert(u->load_state == UNIT_STUB);
|
||||
|
||||
- r = set_ensure_allocated(&s->peers_by_address, &peer_address_hash_ops);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
-
|
||||
r = unit_load_fragment_and_dropin(u, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -485,12 +481,13 @@ static int socket_load(Unit *u) {
|
||||
static SocketPeer *socket_peer_new(void) {
|
||||
SocketPeer *p;
|
||||
|
||||
- p = new0(SocketPeer, 1);
|
||||
+ p = new(SocketPeer, 1);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
- p->n_ref = 1;
|
||||
-
|
||||
+ *p = (SocketPeer) {
|
||||
+ .n_ref = 1,
|
||||
+ };
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -507,14 +504,15 @@ DEFINE_TRIVIAL_REF_UNREF_FUNC(SocketPeer, socket_peer, socket_peer_free);
|
||||
|
||||
int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
|
||||
_cleanup_(socket_peer_unrefp) SocketPeer *remote = NULL;
|
||||
- SocketPeer sa = {}, *i;
|
||||
- socklen_t salen = sizeof(sa.peer);
|
||||
+ SocketPeer sa = {
|
||||
+ .peer_salen = sizeof(union sockaddr_union),
|
||||
+ }, *i;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(s);
|
||||
|
||||
- if (getpeername(fd, &sa.peer.sa, &salen) < 0)
|
||||
+ if (getpeername(fd, &sa.peer.sa, &sa.peer_salen) < 0)
|
||||
return log_unit_error_errno(UNIT(s), errno, "getpeername failed: %m");
|
||||
|
||||
if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) {
|
||||
@@ -522,6 +520,10 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ r = set_ensure_allocated(&s->peers_by_address, &peer_address_hash_ops);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
i = set_get(s->peers_by_address, &sa);
|
||||
if (i) {
|
||||
*p = socket_peer_ref(i);
|
||||
@@ -533,7 +535,7 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
|
||||
return log_oom();
|
||||
|
||||
remote->peer = sa.peer;
|
||||
- remote->peer_salen = salen;
|
||||
+ remote->peer_salen = sa.peer_salen;
|
||||
|
||||
r = set_put(s->peers_by_address, remote);
|
||||
if (r < 0)
|
||||
@@ -542,7 +544,6 @@ int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
|
||||
remote->socket = s;
|
||||
|
||||
*p = TAKE_PTR(remote);
|
||||
-
|
||||
return 1;
|
||||
}
|
||||
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,125 @@
|
||||
From 4ea517a6e07f47117348c68c6fe087bf6d401558 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 16 Feb 2023 15:41:55 +0100
|
||||
Subject: [PATCH] strv: add strv_copy_n() helper for copying part of a n strv
|
||||
|
||||
Conflict:Context Adaptation. Test case adaptation.
|
||||
Reference:https://github.com/systemd/systemd/commit/4ea517a6e07f47117348c68c6fe087bf6d401558
|
||||
|
||||
---
|
||||
src/basic/strv.c | 10 ++++++++--
|
||||
src/basic/strv.h | 5 ++++-
|
||||
src/test/test-strv.c | 41 +++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 53 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/src/basic/strv.c b/src/basic/strv.c
|
||||
index 6a2e44c..d6c50f5 100644
|
||||
--- a/src/basic/strv.c
|
||||
+++ b/src/basic/strv.c
|
||||
@@ -88,20 +88,26 @@ char** strv_free_erase(char **l) {
|
||||
return mfree(l);
|
||||
}
|
||||
|
||||
-char** strv_copy(char * const *l) {
|
||||
+char** strv_copy_n(char * const *l, size_t m) {
|
||||
_cleanup_strv_free_ char **result = NULL;
|
||||
char **k, * const *i;
|
||||
|
||||
- result = new(char*, strv_length(l) + 1);
|
||||
+ result = new(char*, MIN(strv_length(l), m) + 1);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
k = result;
|
||||
STRV_FOREACH(i, l) {
|
||||
+ if (m == 0)
|
||||
+ break;
|
||||
+
|
||||
*k = strdup(*i);
|
||||
if (!*k)
|
||||
return NULL;
|
||||
k++;
|
||||
+
|
||||
+ if (m != SIZE_MAX)
|
||||
+ m--;
|
||||
}
|
||||
|
||||
*k = NULL;
|
||||
diff --git a/src/basic/strv.h b/src/basic/strv.h
|
||||
index 8674bfd..108ec25 100644
|
||||
--- a/src/basic/strv.h
|
||||
+++ b/src/basic/strv.h
|
||||
@@ -29,7 +29,10 @@ char** strv_free_erase(char **l);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free_erase);
|
||||
#define _cleanup_strv_free_erase_ _cleanup_(strv_free_erasep)
|
||||
|
||||
-char** strv_copy(char * const *l);
|
||||
+char** strv_copy_n(char * const *l, size_t n);
|
||||
+static inline char** strv_copy(char * const *l) {
|
||||
+ return strv_copy_n(l, SIZE_MAX);
|
||||
+}
|
||||
size_t strv_length(char * const *l) _pure_;
|
||||
|
||||
int strv_extend_strv(char ***a, char * const *b, bool filter_duplicates);
|
||||
diff --git a/src/test/test-strv.c b/src/test/test-strv.c
|
||||
index 1345252..dd119a8 100644
|
||||
--- a/src/test/test-strv.c
|
||||
+++ b/src/test/test-strv.c
|
||||
@@ -988,6 +988,46 @@ static void test_strv_fnmatch(void) {
|
||||
assert(pos == 1);
|
||||
}
|
||||
|
||||
+static void test_strv_copy_n(void) {
|
||||
+ char **x = STRV_MAKE("a", "b", "c", "d", "e");
|
||||
+ _cleanup_strv_free_ char **l = NULL;
|
||||
+
|
||||
+ l = strv_copy_n(x, 0);
|
||||
+ assert_se(strv_equal(l, NULL));
|
||||
+ strv_free(l);
|
||||
+
|
||||
+ l = strv_copy_n(x, 0);
|
||||
+ assert_se(strv_equal(l, (char**) { NULL }));
|
||||
+ strv_free(l);
|
||||
+
|
||||
+ l = strv_copy_n(x, 1);
|
||||
+ assert_se(strv_equal(l, STRV_MAKE("a")));
|
||||
+ strv_free(l);
|
||||
+
|
||||
+ l = strv_copy_n(x, 2);
|
||||
+ assert_se(strv_equal(l, STRV_MAKE("a", "b")));
|
||||
+ strv_free(l);
|
||||
+
|
||||
+ l = strv_copy_n(x, 3);
|
||||
+ assert_se(strv_equal(l, STRV_MAKE("a", "b", "c")));
|
||||
+ strv_free(l);
|
||||
+
|
||||
+ l = strv_copy_n(x, 4);
|
||||
+ assert_se(strv_equal(l, STRV_MAKE("a", "b", "c", "d")));
|
||||
+ strv_free(l);
|
||||
+
|
||||
+ l = strv_copy_n(x, 5);
|
||||
+ assert_se(strv_equal(l, STRV_MAKE("a", "b", "c", "d", "e")));
|
||||
+ strv_free(l);
|
||||
+
|
||||
+ l = strv_copy_n(x, 6);
|
||||
+ assert_se(strv_equal(l, STRV_MAKE("a", "b", "c", "d", "e")));
|
||||
+ strv_free(l);
|
||||
+
|
||||
+ l = strv_copy_n(x, SIZE_MAX);
|
||||
+ assert_se(strv_equal(l, STRV_MAKE("a", "b", "c", "d", "e")));
|
||||
+}
|
||||
+
|
||||
int main(int argc, char *argv[]) {
|
||||
test_str_in_set();
|
||||
test_strptr_in_set();
|
||||
@@ -1054,6 +1094,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
test_foreach_string();
|
||||
test_strv_fnmatch();
|
||||
+ test_strv_copy_n();
|
||||
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,56 @@
|
||||
From 9eb814818d0c35f0c9e05cb596508c1536b0e654 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Wed, 16 Mar 2022 22:29:32 +0900
|
||||
Subject: [PATCH] strv: rewrite strv_copy() with cleanup attribute and
|
||||
STRV_FOREACH()
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd/commit/9eb814818d0c35f0c9e05cb596508c1536b0e654
|
||||
|
||||
---
|
||||
src/basic/strv.c | 24 ++++++++++++------------
|
||||
1 file changed, 12 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/src/basic/strv.c b/src/basic/strv.c
|
||||
index cf573a3783..07a6c49b50 100644
|
||||
--- a/src/basic/strv.c
|
||||
+++ b/src/basic/strv.c
|
||||
@@ -89,23 +89,23 @@ char** strv_free_erase(char **l) {
|
||||
}
|
||||
|
||||
char** strv_copy(char * const *l) {
|
||||
- char **r, **k;
|
||||
+ _cleanup_strv_free_ char **result = NULL;
|
||||
+ char **k, * const *i;
|
||||
|
||||
- k = r = new(char*, strv_length(l) + 1);
|
||||
- if (!r)
|
||||
+ result = new(char*, strv_length(l) + 1);
|
||||
+ if (!result)
|
||||
return NULL;
|
||||
|
||||
- if (l)
|
||||
- for (; *l; k++, l++) {
|
||||
- *k = strdup(*l);
|
||||
- if (!*k) {
|
||||
- strv_free(r);
|
||||
- return NULL;
|
||||
- }
|
||||
- }
|
||||
+ k = result;
|
||||
+ STRV_FOREACH(i, l) {
|
||||
+ *k = strdup(*i);
|
||||
+ if (!*k)
|
||||
+ return NULL;
|
||||
+ k++;
|
||||
+ }
|
||||
|
||||
*k = NULL;
|
||||
- return r;
|
||||
+ return TAKE_PTR(result);
|
||||
}
|
||||
|
||||
size_t strv_length(char * const *l) {
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,160 @@
|
||||
From b64f5ddacad725d5e4e021691fad52aa2eb32c46 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Yuan <me@yhndnzj.com>
|
||||
Date: Wed, 22 Mar 2023 03:40:52 +0800
|
||||
Subject: [PATCH] test: add tests for NOTIFYACCESS override through sd_notify
|
||||
|
||||
Conflict:Adaptation Context.
|
||||
Reference:https://github.com/systemd/systemd/commit/b64f5ddacad725d5e4e021691fad52aa2eb32c46
|
||||
|
||||
---
|
||||
test/TEST-80-NOTIFYACCESS/Makefile | 1 +
|
||||
test/TEST-80-NOTIFYACCESS/test.sh | 11 +++++++++
|
||||
test/meson.build | 3 +++
|
||||
test/testsuite-80.units/notify.service | 4 ++++
|
||||
test/testsuite-80.units/test.sh | 26 +++++++++++++++++++++
|
||||
test/units/testsuite-80.service | 8 +++++++
|
||||
test/units/testsuite-80.sh | 32 ++++++++++++++++++++++++++
|
||||
7 files changed, 85 insertions(+)
|
||||
create mode 120000 test/TEST-80-NOTIFYACCESS/Makefile
|
||||
create mode 100755 test/TEST-80-NOTIFYACCESS/test.sh
|
||||
create mode 100644 test/testsuite-80.units/notify.service
|
||||
create mode 100755 test/testsuite-80.units/test.sh
|
||||
create mode 100644 test/units/testsuite-80.service
|
||||
create mode 100755 test/units/testsuite-80.sh
|
||||
|
||||
diff --git a/test/TEST-80-NOTIFYACCESS/Makefile b/test/TEST-80-NOTIFYACCESS/Makefile
|
||||
new file mode 120000
|
||||
index 0000000..e9f93b1
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-80-NOTIFYACCESS/Makefile
|
||||
@@ -0,0 +1 @@
|
||||
+../TEST-01-BASIC/Makefile
|
||||
\ No newline at end of file
|
||||
diff --git a/test/TEST-80-NOTIFYACCESS/test.sh b/test/TEST-80-NOTIFYACCESS/test.sh
|
||||
new file mode 100755
|
||||
index 0000000..b4d2452
|
||||
--- /dev/null
|
||||
+++ b/test/TEST-80-NOTIFYACCESS/test.sh
|
||||
@@ -0,0 +1,11 @@
|
||||
+#!/usr/bin/env bash
|
||||
+# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
+set -e
|
||||
+
|
||||
+TEST_DESCRIPTION="test NotifyAccess through sd-notify"
|
||||
+TEST_NO_QEMU=1
|
||||
+
|
||||
+# shellcheck source=test/test-functions
|
||||
+. "${TEST_BASE_DIR:?}/test-functions"
|
||||
+
|
||||
+do_test "$@"
|
||||
diff --git a/test/meson.build b/test/meson.build
|
||||
index 8727e66..8eb9bc4 100644
|
||||
--- a/test/meson.build
|
||||
+++ b/test/meson.build
|
||||
@@ -51,6 +51,9 @@ if install_tests
|
||||
install_subdir('testsuite-63.units',
|
||||
exclude_files : '.gitattributes',
|
||||
install_dir : testdata_dir)
|
||||
+ install_subdir('testsuite-80.units',
|
||||
+ exclude_files : '.gitattributes',
|
||||
+ install_dir : testdata_dir)
|
||||
|
||||
testsuite08_dir = testdata_dir + '/testsuite-08.units'
|
||||
install_data('testsuite-08.units/-.mount',
|
||||
diff --git a/test/testsuite-80.units/notify.service b/test/testsuite-80.units/notify.service
|
||||
new file mode 100644
|
||||
index 0000000..196b076
|
||||
--- /dev/null
|
||||
+++ b/test/testsuite-80.units/notify.service
|
||||
@@ -0,0 +1,4 @@
|
||||
+[Service]
|
||||
+Type=notify
|
||||
+NotifyAccess=all
|
||||
+ExecStart=/usr/lib/systemd/tests/testdata/testsuite-80.units/test.sh
|
||||
diff --git a/test/testsuite-80.units/test.sh b/test/testsuite-80.units/test.sh
|
||||
new file mode 100755
|
||||
index 0000000..3ca71d5
|
||||
--- /dev/null
|
||||
+++ b/test/testsuite-80.units/test.sh
|
||||
@@ -0,0 +1,26 @@
|
||||
+#!/usr/bin/env bash
|
||||
+# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
+# shellcheck disable=SC2016
|
||||
+set -eux
|
||||
+set -o pipefail
|
||||
+
|
||||
+systemd-notify --status="Test starts, waiting for 5 seconds"
|
||||
+sleep 5
|
||||
+
|
||||
+(
|
||||
+ systemd-notify --pid=auto
|
||||
+ systemd-notify "NOTIFYACCESS=main"
|
||||
+
|
||||
+ systemd-notify --status="Sending READY=1 in an unpriviledged process"
|
||||
+ (
|
||||
+ sleep 0.1
|
||||
+ systemd-notify --ready
|
||||
+ )
|
||||
+ sleep 10
|
||||
+
|
||||
+ systemd-notify "MAINPID=$$"
|
||||
+)
|
||||
+
|
||||
+systemd-notify --ready --status="OK"
|
||||
+systemd-notify "NOTIFYACCESS=none"
|
||||
+sleep infinity
|
||||
diff --git a/test/units/testsuite-80.service b/test/units/testsuite-80.service
|
||||
new file mode 100644
|
||||
index 0000000..4c7f5d5
|
||||
--- /dev/null
|
||||
+++ b/test/units/testsuite-80.service
|
||||
@@ -0,0 +1,8 @@
|
||||
+# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
+[Unit]
|
||||
+Description=TEST-80-NOTIFYACCESS
|
||||
+
|
||||
+[Service]
|
||||
+ExecStartPre=rm -f /failed /testok
|
||||
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
|
||||
+Type=oneshot
|
||||
diff --git a/test/units/testsuite-80.sh b/test/units/testsuite-80.sh
|
||||
new file mode 100755
|
||||
index 0000000..5f57569
|
||||
--- /dev/null
|
||||
+++ b/test/units/testsuite-80.sh
|
||||
@@ -0,0 +1,32 @@
|
||||
+#!/usr/bin/env bash
|
||||
+# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
+# shellcheck disable=SC2016
|
||||
+set -eux
|
||||
+set -o pipefail
|
||||
+
|
||||
+# shellcheck source=test/units/assert.sh
|
||||
+. "$(dirname "$0")"/assert.sh
|
||||
+
|
||||
+: >/failed
|
||||
+
|
||||
+systemctl --no-block start notify.service
|
||||
+sleep 2
|
||||
+
|
||||
+assert_eq "$(systemctl show notify.service -p StatusText --value)" "Test starts, waiting for 5 seconds"
|
||||
+assert_eq "$(systemctl show notify.service -p NotifyAccess --value)" "all"
|
||||
+sleep 5
|
||||
+
|
||||
+assert_eq "$(systemctl show notify.service -p NotifyAccess --value)" "main"
|
||||
+assert_eq "$(systemctl show notify.service -p StatusText --value)" "Sending READY=1 in an unpriviledged process"
|
||||
+assert_rc 3 systemctl --quiet is-active notify.service
|
||||
+sleep 10
|
||||
+
|
||||
+systemctl --quiet is-active notify.service
|
||||
+assert_eq "$(systemctl show notify.service -p StatusText --value)" "OK"
|
||||
+assert_eq "$(systemctl show notify.service -p NotifyAccess --value)" "none"
|
||||
+
|
||||
+systemctl stop notify.service
|
||||
+assert_eq "$(systemctl show notify.service -p NotifyAccess --value)" "all"
|
||||
+
|
||||
+touch /testok
|
||||
+rm /failed
|
||||
--
|
||||
2.33.0
|
||||
|
||||
186
backport-test-validate-that-fdstore-pinning-works.patch
Normal file
186
backport-test-validate-that-fdstore-pinning-works.patch
Normal file
@ -0,0 +1,186 @@
|
||||
From 3540ce8587cbd21ce9c2dbec72ea7fa3d1b38a5f Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Tue, 4 Apr 2023 11:41:55 +0200
|
||||
Subject: [PATCH] test: validate that fdstore pinning works
|
||||
|
||||
Conflict:Adaptation Context.
|
||||
Reference:https://github.com/systemd/systemd/commit/3540ce8587cbd21ce9c2dbec72ea7fa3d1b38a5f
|
||||
|
||||
---
|
||||
test/testsuite-80.units/fdstore-nopin.service | 8 +++
|
||||
test/testsuite-80.units/fdstore-pin.service | 8 +++
|
||||
test/testsuite-80.units/fdstore-pin.sh | 47 +++++++++++++++++
|
||||
test/testsuite-80.units/fdstore-pin.target | 3 ++
|
||||
test/units/testsuite-80.service | 2 +
|
||||
test/units/testsuite-80.sh | 51 +++++++++++++++++++
|
||||
6 files changed, 119 insertions(+)
|
||||
create mode 100644 test/testsuite-80.units/fdstore-nopin.service
|
||||
create mode 100644 test/testsuite-80.units/fdstore-pin.service
|
||||
create mode 100755 test/testsuite-80.units/fdstore-pin.sh
|
||||
create mode 100644 test/testsuite-80.units/fdstore-pin.target
|
||||
|
||||
diff --git a/test/testsuite-80.units/fdstore-nopin.service b/test/testsuite-80.units/fdstore-nopin.service
|
||||
new file mode 100644
|
||||
index 0000000..58a687a
|
||||
--- /dev/null
|
||||
+++ b/test/testsuite-80.units/fdstore-nopin.service
|
||||
@@ -0,0 +1,8 @@
|
||||
+[Service]
|
||||
+Type=notify
|
||||
+NotifyAccess=all
|
||||
+FileDescriptorStoreMax=10
|
||||
+FileDescriptorStorePreserve=restart
|
||||
+ExecStart=/usr/lib/systemd/tests/testdata/testsuite-80.units/fdstore-pin.sh 0
|
||||
+StandardOutput=journal+console
|
||||
+StandardError=journal+console
|
||||
diff --git a/test/testsuite-80.units/fdstore-pin.service b/test/testsuite-80.units/fdstore-pin.service
|
||||
new file mode 100644
|
||||
index 0000000..bc78ee0
|
||||
--- /dev/null
|
||||
+++ b/test/testsuite-80.units/fdstore-pin.service
|
||||
@@ -0,0 +1,8 @@
|
||||
+[Service]
|
||||
+Type=notify
|
||||
+NotifyAccess=all
|
||||
+FileDescriptorStoreMax=10
|
||||
+FileDescriptorStorePreserve=yes
|
||||
+ExecStart=/usr/lib/systemd/tests/testdata/testsuite-80.units/fdstore-pin.sh 1
|
||||
+StandardOutput=journal+console
|
||||
+StandardError=journal+console
|
||||
diff --git a/test/testsuite-80.units/fdstore-pin.sh b/test/testsuite-80.units/fdstore-pin.sh
|
||||
new file mode 100755
|
||||
index 0000000..4cb041a
|
||||
--- /dev/null
|
||||
+++ b/test/testsuite-80.units/fdstore-pin.sh
|
||||
@@ -0,0 +1,47 @@
|
||||
+#!/usr/bin/env bash
|
||||
+# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
+set -eux
|
||||
+set -o pipefail
|
||||
+
|
||||
+PINNED="$1"
|
||||
+COUNTER="/tmp/fdstore-invoked.$PINNED"
|
||||
+FILE="/tmp/fdstore-data.$PINNED"
|
||||
+
|
||||
+# This script is called six times: thrice from a service unit where the fdstore
|
||||
+# is pinned, and thrice where it isn't. The second iteration of each series is
|
||||
+# a restart, the third a stop followed by a start
|
||||
+
|
||||
+if [ -e "$COUNTER" ] ; then
|
||||
+ read -r N < "$COUNTER"
|
||||
+else
|
||||
+ N=0
|
||||
+fi
|
||||
+
|
||||
+echo "Invocation #$N with PINNED=$PINNED."
|
||||
+
|
||||
+if [ "$N" -eq 0 ] ; then
|
||||
+ # First iteration
|
||||
+ test "${LISTEN_FDS:-0}" -eq 0
|
||||
+ test ! -e "$FILE"
|
||||
+ echo waldi > "$FILE"
|
||||
+ systemd-notify --fd=3 --fdname="fd-$N-$PINNED" 3< "$FILE"
|
||||
+elif [ "$N" -eq 1 ] || { [ "$N" -eq 2 ] && [ "$PINNED" -eq 1 ]; } ; then
|
||||
+ # Second iteration, or iteration with pinning on
|
||||
+ test "${LISTEN_FDS:-0}" -eq 1
|
||||
+ # We reopen fd #3 here, so that the read offset is at zero each time (hence no <&3 here…)
|
||||
+ read -r word < /proc/self/fd/3
|
||||
+ test "$word" = "waldi"
|
||||
+else
|
||||
+ test "${LISTEN_FDS:-0}" -eq 0
|
||||
+ test -e "$FILE"
|
||||
+fi
|
||||
+
|
||||
+if [ "$N" -ge 2 ] ; then
|
||||
+ rm "$COUNTER" "$FILE"
|
||||
+else
|
||||
+ echo $((N + 1)) > "$COUNTER"
|
||||
+fi
|
||||
+
|
||||
+systemd-notify --ready --status="Ready"
|
||||
+
|
||||
+exec sleep infinity
|
||||
diff --git a/test/testsuite-80.units/fdstore-pin.target b/test/testsuite-80.units/fdstore-pin.target
|
||||
new file mode 100644
|
||||
index 0000000..319b7e1
|
||||
--- /dev/null
|
||||
+++ b/test/testsuite-80.units/fdstore-pin.target
|
||||
@@ -0,0 +1,3 @@
|
||||
+[Unit]
|
||||
+After=fdstore-pin.service fdstore-nopin.service
|
||||
+Wants=fdstore-pin.service fdstore-nopin.service
|
||||
diff --git a/test/units/testsuite-80.service b/test/units/testsuite-80.service
|
||||
index 4c7f5d5..82b08a1 100644
|
||||
--- a/test/units/testsuite-80.service
|
||||
+++ b/test/units/testsuite-80.service
|
||||
@@ -6,3 +6,5 @@ Description=TEST-80-NOTIFYACCESS
|
||||
ExecStartPre=rm -f /failed /testok
|
||||
ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
|
||||
Type=oneshot
|
||||
+StandardOutput=journal+console
|
||||
+StandardError=journal+console
|
||||
diff --git a/test/units/testsuite-80.sh b/test/units/testsuite-80.sh
|
||||
index 43647a7..9a979b9 100755
|
||||
--- a/test/units/testsuite-80.sh
|
||||
+++ b/test/units/testsuite-80.sh
|
||||
@@ -48,5 +48,56 @@ assert_eq "$(systemctl show notify.service -p NotifyAccess --value)" "all"
|
||||
|
||||
rm /tmp/syncfifo1 /tmp/syncfifo2
|
||||
|
||||
+# Now test basic fdstore behaviour
|
||||
+
|
||||
+systemd-analyze log-level debug
|
||||
+
|
||||
+# Test fdstore pinning (this will pull in fdstore-pin.service fdstore-nopin.service)
|
||||
+systemctl start fdstore-pin.target
|
||||
+
|
||||
+assert_eq "$(systemctl show fdstore-pin.service -P FileDescriptorStorePreserve)" yes
|
||||
+assert_eq "$(systemctl show fdstore-nopin.service -P FileDescriptorStorePreserve)" restart
|
||||
+assert_eq "$(systemctl show fdstore-pin.service -P SubState)" running
|
||||
+assert_eq "$(systemctl show fdstore-nopin.service -P SubState)" running
|
||||
+assert_eq "$(systemctl show fdstore-pin.service -P NFileDescriptorStore)" 1
|
||||
+assert_eq "$(systemctl show fdstore-nopin.service -P NFileDescriptorStore)" 1
|
||||
+
|
||||
+# The file descriptor store should survive service restarts
|
||||
+systemctl restart fdstore-pin.service fdstore-nopin.service
|
||||
+
|
||||
+assert_eq "$(systemctl show fdstore-pin.service -P NFileDescriptorStore)" 1
|
||||
+assert_eq "$(systemctl show fdstore-nopin.service -P NFileDescriptorStore)" 1
|
||||
+assert_eq "$(systemctl show fdstore-pin.service -P SubState)" running
|
||||
+assert_eq "$(systemctl show fdstore-nopin.service -P SubState)" running
|
||||
+
|
||||
+# It should not survive the service stop plus a later start (unless pinned)
|
||||
+systemctl stop fdstore-pin.service fdstore-nopin.service
|
||||
+
|
||||
+assert_eq "$(systemctl show fdstore-pin.service -P NFileDescriptorStore)" 1
|
||||
+assert_eq "$(systemctl show fdstore-nopin.service -P NFileDescriptorStore)" 0
|
||||
+assert_eq "$(systemctl show fdstore-pin.service -P SubState)" dead-resources-pinned
|
||||
+assert_eq "$(systemctl show fdstore-nopin.service -P SubState)" dead
|
||||
+
|
||||
+systemctl start fdstore-pin.service fdstore-nopin.service
|
||||
+
|
||||
+assert_eq "$(systemctl show fdstore-pin.service -P NFileDescriptorStore)" 1
|
||||
+assert_eq "$(systemctl show fdstore-nopin.service -P NFileDescriptorStore)" 0
|
||||
+assert_eq "$(systemctl show fdstore-pin.service -P SubState)" running
|
||||
+assert_eq "$(systemctl show fdstore-nopin.service -P SubState)" running
|
||||
+
|
||||
+systemctl stop fdstore-pin.service fdstore-nopin.service
|
||||
+
|
||||
+assert_eq "$(systemctl show fdstore-pin.service -P NFileDescriptorStore)" 1
|
||||
+assert_eq "$(systemctl show fdstore-nopin.service -P NFileDescriptorStore)" 0
|
||||
+assert_eq "$(systemctl show fdstore-pin.service -P SubState)" dead-resources-pinned
|
||||
+assert_eq "$(systemctl show fdstore-nopin.service -P SubState)" dead
|
||||
+
|
||||
+systemctl clean fdstore-pin.service --what=fdstore
|
||||
+
|
||||
+assert_eq "$(systemctl show fdstore-pin.service -P NFileDescriptorStore)" 0
|
||||
+assert_eq "$(systemctl show fdstore-nopin.service -P NFileDescriptorStore)" 0
|
||||
+assert_eq "$(systemctl show fdstore-pin.service -P SubState)" dead
|
||||
+assert_eq "$(systemctl show fdstore-nopin.service -P SubState)" dead
|
||||
+
|
||||
touch /testok
|
||||
rm /failed
|
||||
|
||||
--
|
||||
2.33.0
|
||||
|
||||
49
backport-unit-don-t-gc-unit-in-oom-queue.patch
Normal file
49
backport-unit-don-t-gc-unit-in-oom-queue.patch
Normal file
@ -0,0 +1,49 @@
|
||||
From 935f80428fd3220c83163cc4b5a637873e68babb Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
Date: Thu, 8 Jun 2023 11:11:28 +0200
|
||||
Subject: [PATCH] unit: don't gc unit in oom queue
|
||||
|
||||
This is a follow-up for 8db998981a4fefd0122bcf5f965726b63c9045c2, and
|
||||
follows a similar logic: a pending OOM event really trumps everything:
|
||||
we should not GC a unit while it is pending.
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://github.com/systemd/systemd/commit/935f80428fd3220c83163cc4b5a637873e68babb
|
||||
|
||||
---
|
||||
src/core/cgroup.c | 2 ++
|
||||
src/core/unit.c | 5 ++++-
|
||||
2 files changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
|
||||
index 839b1676c8..34643b242c 100644
|
||||
--- a/src/core/cgroup.c
|
||||
+++ b/src/core/cgroup.c
|
||||
@@ -3319,6 +3319,8 @@ static int on_cgroup_oom_event(sd_event_source *s, void *userdata) {
|
||||
}
|
||||
|
||||
(void) unit_check_oom(u);
|
||||
+ unit_add_to_gc_queue(u);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/src/core/unit.c b/src/core/unit.c
|
||||
index 7b6d50e0ea..80f398c309 100644
|
||||
--- a/src/core/unit.c
|
||||
+++ b/src/core/unit.c
|
||||
@@ -441,7 +441,10 @@ bool unit_may_gc(Unit *u) {
|
||||
if (u->perpetual)
|
||||
return false;
|
||||
|
||||
- if (u->in_cgroup_empty_queue)
|
||||
+ /* if we saw a cgroup empty event for this unit, stay around until we processed it so that we remove
|
||||
+ * the empty cgroup if possible. Similar, process any pending OOM events if they are already queued
|
||||
+ * before we release the unit. */
|
||||
+ if (u->in_cgroup_empty_queue || u->in_cgroup_oom_queue)
|
||||
return false;
|
||||
|
||||
if (sd_bus_track_count(u->bus_track) > 0)
|
||||
--
|
||||
2.33.0
|
||||
|
||||
34
systemd.spec
34
systemd.spec
@ -21,7 +21,7 @@
|
||||
Name: systemd
|
||||
Url: https://systemd.io/
|
||||
Version: 249
|
||||
Release: 79
|
||||
Release: 80
|
||||
License: MIT and LGPLv2+ and GPLv2+
|
||||
Summary: System and Service Manager
|
||||
|
||||
@ -642,6 +642,35 @@ Patch6593: backport-CVE-2023-50387.patch
|
||||
Patch6594: backport-CVE-2023-50868.patch
|
||||
Patch6595: backport-login-user-runtime-dir-properly-check-for-mount-poin.patch
|
||||
Patch6596: backport-user-util-validate-the-right-field.patch
|
||||
Patch6597: backport-core-fix-property-getter-method-for-NFileDescriptorS.patch
|
||||
Patch6598: backport-Add-implicit-sentinel-to-strv_env_merge.patch
|
||||
Patch6599: backport-basic-strv-inline-variables-and-modernize-style-a-bi.patch
|
||||
Patch6600: backport-strv-rewrite-strv_copy-with-cleanup-attribute-and-ST.patch
|
||||
Patch6601: backport-strv-add-strv_copy_n-helper-for-copying-part-of-a-n-.patch
|
||||
Patch6602: backport-fd-util-introduce-dir_fd_is_root_or_cwd.patch
|
||||
Patch6603: backport-notify-add-new-exec-switch-for-chaining-other-comman.patch
|
||||
Patch6604: backport-fdset-add-new-fdset_consume-helper.patch
|
||||
Patch6605: backport-notify-add-support-for-sending-fds-with-notification.patch
|
||||
Patch6606: backport-socket-various-modernizations.patch
|
||||
Patch6607: backport-socket-always-pass-socket-fd-and-SocketPeer-ownershi.patch
|
||||
Patch6608: backport-fdset-add-new-helper-to-convert-an-fdset-to-an-array.patch
|
||||
Patch6609: backport-service-release-resources-from-a-seperate-queue-not-.patch
|
||||
Patch6610: backport-service-drop-redundant-unit_ref_unset-call.patch
|
||||
Patch6611: backport-service-rework-how-we-release-resources.patch
|
||||
Patch6612: backport-service-add-ability-to-pin-fd-store.patch
|
||||
Patch6613: backport-service-allow-freeing-the-fdstore-via-cleaning.patch
|
||||
Patch6614: backport-service-close-fdstore-asynchronously.patch
|
||||
Patch6615: backport-core-move-runtime-directory-removal-into-release_res.patch
|
||||
Patch6616: backport-service-rename-service_close_socket_fd-service_relea.patch
|
||||
Patch6617: backport-pid1-add-some-debug-logging-when-stashing-ds-into-th.patch
|
||||
Patch6618: backport-meson-exclude-.gitattributes-when-using-install_subd.patch
|
||||
Patch6619: backport-core-support-overriding-NOTIFYACCESS-through-sd-noti.patch
|
||||
Patch6620: backport-test-add-tests-for-NOTIFYACCESS-override-through-sd_.patch
|
||||
Patch6621: backport-TEST-80-synchronize-explicitly-instead-of-by-time.patch
|
||||
Patch6622: backport-test-validate-that-fdstore-pinning-works.patch
|
||||
Patch6623: backport-core-Don-t-GC-unit-if-it-is-in-cgroup_empty_queue.patch
|
||||
Patch6624: backport-unit-don-t-gc-unit-in-oom-queue.patch
|
||||
Patch6625: backport-core-do-not-GC-units-jobs-that-are-in-the-D-Bus-queu.patch
|
||||
|
||||
Patch9001: update-rtc-with-system-clock-when-shutdown.patch
|
||||
Patch9002: udev-add-actions-while-rename-netif-failed.patch
|
||||
@ -2156,6 +2185,9 @@ grep -q -E '^KEYMAP="?fi-latin[19]"?' /etc/vconsole.conf 2>/dev/null &&
|
||||
/usr/bin/systemd-cryptenroll
|
||||
|
||||
%changelog
|
||||
* Mon Jun 17 2024 zhangyao <zhangyao108@huawei.com> - 249-80
|
||||
- Add the FileDescriptorStorePreserve= option to the service
|
||||
|
||||
* Tue Jun 11 2024 wangyuhang <wangyuhang27@huawei.com> - 249-79
|
||||
- extract systemd-cryptsetup
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user