From ad929bcc27e2c6c1aa731053e45882686e9babab Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 4 Jul 2013 20:31:18 +0200 Subject: [PATCH 4/6] disable the cgroups release agent when shutting down During shutdown, when we try to clean up all remaining processes, the kernel will fork new agents every time a cgroup runs empty. These new processes cause delays in the final SIGTERM, SIGKILL logic. Apart from that, this should also avoid that the kernel-forked binaries cause unpredictably timed access to the filesystem which we might need to unmount. --- src/core/main.c | 4 ++++ src/shared/cgroup-util.c | 15 +++++++++++++++ src/shared/cgroup-util.h | 1 + 3 files changed, 20 insertions(+) diff --git a/src/core/main.c b/src/core/main.c index 8b8e110..ada0f9d 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1942,6 +1942,10 @@ finish: watchdog_close(true); } + /* avoid the creation of new processes forked by the kernel; at this + * point, we will not listen to the signals anyway */ + cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER); + execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block); free(env_block); log_error("Failed to execute shutdown binary, freezing: %m"); diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 390259e..73013d1 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -790,6 +790,21 @@ int cg_install_release_agent(const char *controller, const char *agent) { return 0; } +int cg_uninstall_release_agent(const char *controller) { + _cleanup_free_ char *fs = NULL; + int r; + + r = cg_get_path(controller, NULL, "release_agent", &fs); + if (r < 0) + return r; + + r = write_string_file(fs, ""); + if (r < 0) + return r; + + return 0; +} + int cg_is_empty(const char *controller, const char *path, bool ignore_self) { _cleanup_fclose_ FILE *f = NULL; pid_t pid = 0, self_pid; diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h index c781aab..0fc93c1 100644 --- a/src/shared/cgroup-util.h +++ b/src/shared/cgroup-util.h @@ -89,6 +89,7 @@ int cg_set_group_access(const char *controller, const char *path, mode_t mode, u int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid); int cg_install_release_agent(const char *controller, const char *agent); +int cg_uninstall_release_agent(const char *controller); int cg_is_empty(const char *controller, const char *path, bool ignore_self); int cg_is_empty_by_spec(const char *spec, bool ignore_self); -- 1.8.1.4