chiark / gitweb /
service: explicitly remove control/ subcgroup after each control command
authorLennart Poettering <lennart@poettering.net>
Thu, 3 May 2012 19:54:44 +0000 (21:54 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 3 May 2012 19:54:44 +0000 (21:54 +0200)
The kernel will only notify us of cgroups running empty if no subcgroups
exist anymore. Hence make sure we don't leave our own control/ subcgroup
around longer than necessary.

https://bugzilla.redhat.com/show_bug.cgi?id=818381

src/core/cgroup.c
src/core/cgroup.h
src/core/mount.c
src/core/service.c
src/core/socket.c
src/core/swap.c

index e07d1ed..713c1ca 100644 (file)
@@ -194,7 +194,7 @@ int cgroup_bonding_set_task_access_list(CGroupBonding *first, mode_t mode, uid_t
         return 0;
 }
 
-int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s, const char *cgroup_suffix) {
+int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, bool rem, Set *s, const char *cgroup_suffix) {
         char *p = NULL;
         const char *path;
         int r;
@@ -215,13 +215,13 @@ int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s, const c
         } else
                 path = b->path;
 
-        r = cg_kill_recursive(b->controller, path, sig, sigcont, true, false, s);
+        r = cg_kill_recursive(b->controller, path, sig, sigcont, true, rem, s);
         free(p);
 
         return r;
 }
 
-int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, Set *s, const char *cgroup_suffix) {
+int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, bool rem, Set *s, const char *cgroup_suffix) {
         CGroupBonding *b;
         Set *allocated_set = NULL;
         int ret = -EAGAIN, r;
@@ -234,7 +234,7 @@ int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, Set *s
                         return -ENOMEM;
 
         LIST_FOREACH(by_unit, b, first) {
-                r = cgroup_bonding_kill(b, sig, sigcont, s, cgroup_suffix);
+                r = cgroup_bonding_kill(b, sig, sigcont, rem, s, cgroup_suffix);
                 if (r < 0) {
                         if (r == -EAGAIN || r == -ESRCH)
                                 continue;
index 95f09e0..65fbe4d 100644 (file)
@@ -65,8 +65,8 @@ int cgroup_bonding_set_group_access_list(CGroupBonding *b, mode_t mode, uid_t ui
 int cgroup_bonding_set_task_access(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid, int sticky);
 int cgroup_bonding_set_task_access_list(CGroupBonding *b, mode_t mode, uid_t uid, gid_t gid, int sticky);
 
-int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, Set *s, const char *suffix);
-int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, Set *s, const char *suffix);
+int cgroup_bonding_kill(CGroupBonding *b, int sig, bool sigcont, bool rem, Set *s, const char *suffix);
+int cgroup_bonding_kill_list(CGroupBonding *first, int sig, bool sigcont, bool rem, Set *s, const char *suffix);
 
 void cgroup_bonding_trim(CGroupBonding *first, bool delete_root);
 void cgroup_bonding_trim_list(CGroupBonding *first, bool delete_root);
index 5f50d95..8bdd462 100644 (file)
@@ -891,7 +891,7 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
                                 if ((r = set_put(pid_set, LONG_TO_PTR(m->control_pid))) < 0)
                                         goto fail;
 
-                        r = cgroup_bonding_kill_list(UNIT(m)->cgroup_bondings, sig, true, pid_set, NULL);
+                        r = cgroup_bonding_kill_list(UNIT(m)->cgroup_bondings, sig, true, false, pid_set, NULL);
                         if (r < 0) {
                                 if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
                                         log_warning("Failed to kill control group: %s", strerror(-r));
@@ -1850,7 +1850,7 @@ static int mount_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError
                                 goto finish;
                         }
 
-                q = cgroup_bonding_kill_list(UNIT(m)->cgroup_bondings, signo, false, pid_set, NULL);
+                q = cgroup_bonding_kill_list(UNIT(m)->cgroup_bondings, signo, false, false, pid_set, NULL);
                 if (q < 0)
                         if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
                                 r = q;
index 02d1aa8..40f1682 100644 (file)
@@ -1964,7 +1964,7 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f
                                 if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
                                         goto fail;
 
-                        r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, pid_set, NULL);
+                        r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, false, pid_set, NULL);
                         if (r < 0) {
                                 if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
                                         log_warning("Failed to kill control group: %s", strerror(-r));
@@ -2111,7 +2111,7 @@ static void service_enter_start(Service *s) {
         /* We want to ensure that nobody leaks processes from
          * START_PRE here, so let's go on a killing spree, People
          * should not spawn long running processes from START_PRE. */
-        cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, SIGKILL, true, NULL, "control");
+        cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, SIGKILL, true, true, NULL, "control");
 
         if (s->type == SERVICE_FORKING) {
                 s->control_command_id = SERVICE_EXEC_START;
@@ -2187,7 +2187,7 @@ static void service_enter_start_pre(Service *s) {
 
                 /* Before we start anything, let's clear up what might
                  * be left from previous runs. */
-                cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, SIGKILL, true, NULL, "control");
+                cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, SIGKILL, true, true, NULL, "control");
 
                 s->control_command_id = SERVICE_EXEC_START_PRE;
 
@@ -2924,6 +2924,11 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
                 if (f != SERVICE_SUCCESS)
                         s->result = f;
 
+                /* Immediately get rid of the cgroup, so that the
+                 * kernel doesn't delay the cgroup empty messages for
+                 * the service cgroup any longer than necessary */
+                cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, SIGKILL, true, true, NULL, "control");
+
                 if (s->control_command &&
                     s->control_command->command_next &&
                     f == SERVICE_SUCCESS) {
@@ -3674,7 +3679,7 @@ static int service_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusErro
                                 r = q;
                                 goto finish;
                         }
-                q = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, signo, false, pid_set, NULL);
+                q = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, signo, false, false, pid_set, NULL);
                 if (q < 0)
                         if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
                                 r = q;
index 1d56829..60ea3cb 100644 (file)
@@ -1243,7 +1243,7 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
                                 if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
                                         goto fail;
 
-                        r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, pid_set, NULL);
+                        r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, false, pid_set, NULL);
                         if (r < 0) {
                                 if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
                                         log_warning("Failed to kill control group: %s", strerror(-r));
@@ -2131,7 +2131,7 @@ static int socket_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError
                                 goto finish;
                         }
 
-                q = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, signo, false, pid_set, NULL);
+                q = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, signo, false, false, pid_set, NULL);
                 if (q < 0)
                         if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
                                 r = q;
index d2f9491..3881d28 100644 (file)
@@ -690,7 +690,7 @@ static void swap_enter_signal(Swap *s, SwapState state, SwapResult f) {
                                 if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0)
                                         goto fail;
 
-                        r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, pid_set, NULL);
+                        r = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, sig, true, false, pid_set, NULL);
                         if (r < 0) {
                                 if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
                                         log_warning("Failed to kill control group: %s", strerror(-r));
@@ -1322,7 +1322,7 @@ static int swap_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError *
                                 goto finish;
                         }
 
-                q = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, signo, false, pid_set, NULL);
+                q = cgroup_bonding_kill_list(UNIT(s)->cgroup_bondings, signo, false, false, pid_set, NULL);
                 if (q < 0)
                         if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
                                 r = q;