chiark / gitweb /
gcc: make a couple of gcc warnings go away
[elogind.git] / service.c
index ca6e04500cd7215999d04b2030110c09aac42690..149a791b05f62a8ca76b3a7c732a90f88c8c75ef 100644 (file)
--- a/service.c
+++ b/service.c
@@ -581,6 +581,12 @@ static int service_init(Unit *u) {
                 return r;
         }
 
+        /* Add default cgroup */
+        if ((r = unit_add_default_cgroup(u)) < 0) {
+                service_done(u);
+                return r;
+        }
+
         return 0;
 }
 
@@ -599,10 +605,12 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
         fprintf(f,
                 "%sService State: %s\n"
                 "%sPermissionsStartOnly: %s\n"
-                "%sRootDirectoryStartOnly: %s\n",
+                "%sRootDirectoryStartOnly: %s\n"
+                "%sValidNoProcess: %s\n",
                 prefix, service_state_to_string(s->state),
                 prefix, yes_no(s->permissions_start_only),
-                prefix, yes_no(s->root_directory_start_only));
+                prefix, yes_no(s->root_directory_start_only),
+                prefix, yes_no(s->valid_no_process));
 
         if (s->pid_file)
                 fprintf(f,
@@ -898,6 +906,7 @@ static int service_spawn(
                             fds, n_fds,
                             apply_permissions,
                             apply_chroot,
+                            UNIT(s)->meta.cgroup_bondings,
                             &pid)) < 0)
                 goto fail;
 
@@ -1336,7 +1345,7 @@ static int main_pid_good(Service *s) {
                 return s->main_pid > 0;
 
         /* We don't know the pid */
-        return -1;
+        return -EAGAIN;
 }
 
 static bool control_pid_good(Service *s) {
@@ -1345,6 +1354,15 @@ static bool control_pid_good(Service *s) {
         return s->control_pid > 0;
 }
 
+static int cgroup_good(Service *s) {
+        assert(s);
+
+        if (s->valid_no_process)
+                return -EAGAIN;
+
+        return cgroup_bonding_is_empty_list(UNIT(s)->meta.cgroup_bondings);
+}
+
 static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         Service *s = SERVICE(u);
         bool success;
@@ -1418,7 +1436,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
                  * don't care about failing commands. */
 
                 if (s->control_command->command_next &&
-                    (success || (s->state == SERVICE_EXEC_STOP || s->state == SERVICE_EXEC_STOP_POST)))
+                    (success || (s->state == SERVICE_STOP || s->state == SERVICE_STOP_POST)))
 
                         /* There is another command to *
                          * execute, so let's do that. */
@@ -1477,7 +1495,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 
                         case SERVICE_RELOAD:
                                 if (success) {
-                                        if (main_pid_good(s) != 0)
+                                        if (main_pid_good(s) != 0 && cgroup_good(s) != 0)
                                                 service_set_state(s, SERVICE_RUNNING);
                                         else
                                                 service_enter_stop(s, true);
@@ -1580,6 +1598,33 @@ static void service_timer_event(Unit *u, uint64_t elapsed, Watch* w) {
         }
 }
 
+static void service_cgroup_notify_event(Unit *u) {
+        Service *s = SERVICE(u);
+
+        assert(u);
+
+        log_debug("%s: cgroup is empty", unit_id(u));
+
+        switch (s->state) {
+
+                /* Waiting for SIGCHLD is usually more interesting,
+                 * because it includes return codes/signals. Which is
+                 * why we ignore the cgroup events for most cases,
+                 * except when we don't know pid which to expect the
+                 * SIGCHLD for. */
+
+        case SERVICE_RUNNING:
+
+                if (!s->valid_no_process && main_pid_good(s) <= 0)
+                        service_enter_stop(s, true);
+
+                break;
+
+        default:
+                ;
+        }
+}
+
 static int service_enumerate(Manager *m) {
 
         static const char * const rcnd[] = {
@@ -1658,11 +1703,6 @@ static int service_enumerate(Manager *m) {
                                 if ((r = manager_load_unit(m, name, &service)) < 0)
                                         goto finish;
 
-                                /* Don't allow that non-SysV services
-                                 * are started via rcN.d/ links. */
-                                if (!SERVICE(service)->sysv_path)
-                                        continue;
-
                                 if ((r = manager_load_unit(m, rcnd[i+1], &runlevel)) < 0)
                                         goto finish;
 
@@ -1758,5 +1798,7 @@ const UnitVTable service_vtable = {
         .sigchld_event = service_sigchld_event,
         .timer_event = service_timer_event,
 
+        .cgroup_notify_empty = service_cgroup_notify_event,
+
         .enumerate = service_enumerate
 };