[systemd-commits] 2 commits - src/service.c src/service.h TODO

Lennart Poettering lennart at kemper.freedesktop.org
Thu Jan 20 09:47:37 PST 2011


 TODO          |    2 -
 src/service.c |   72 ++++++++++++++++++++++++++++++++++++++--------------------
 src/service.h |   10 ++++++++
 3 files changed, 58 insertions(+), 26 deletions(-)

New commits:
commit 867b3b7d6b88ba4d07ec7c830576d4ac2f7dd226
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 20 18:46:38 2011 +0100

    service: make chain of main commands and control commands independent of each other, so that both can be executed simultaneously and independently

diff --git a/TODO b/TODO
index 317fe88..4e8c6d1 100644
--- a/TODO
+++ b/TODO
@@ -2,8 +2,6 @@ Bugs:
 
 * Don't try to connect to dbus during early boot
 
-* Fix multiple reload statements
-
 * sometimes processes seem to remain when we kill a service
   http://lists.fedoraproject.org/pipermail/devel/2011-January/147559.html
 
diff --git a/src/service.c b/src/service.c
index 03a858a..60576df 100644
--- a/src/service.c
+++ b/src/service.c
@@ -211,6 +211,7 @@ static void service_done(Unit *u) {
         exec_context_done(&s->exec_context);
         exec_command_free_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX);
         s->control_command = NULL;
+        s->main_command = NULL;
 
         /* This will leak a process, but at least no memory or any of
          * our resources */
@@ -1400,8 +1401,10 @@ static void service_set_state(Service *s, ServiceState state) {
             state != SERVICE_RELOAD &&
             state != SERVICE_STOP &&
             state != SERVICE_STOP_SIGTERM &&
-            state != SERVICE_STOP_SIGKILL)
+            state != SERVICE_STOP_SIGKILL) {
                 service_unwatch_main_pid(s);
+                s->main_command = NULL;
+        }
 
         if (state != SERVICE_START_PRE &&
             state != SERVICE_START &&
@@ -1782,8 +1785,9 @@ static void service_enter_stop_post(Service *s, bool success) {
 
         service_unwatch_control_pid(s);
 
-        s->control_command_id = SERVICE_EXEC_STOP_POST;
         if ((s->control_command = s->exec_command[SERVICE_EXEC_STOP_POST])) {
+                s->control_command_id = SERVICE_EXEC_STOP_POST;
+
                 if ((r = service_spawn(s,
                                        s->control_command,
                                        true,
@@ -1901,8 +1905,9 @@ static void service_enter_stop(Service *s, bool success) {
 
         service_unwatch_control_pid(s);
 
-        s->control_command_id = SERVICE_EXEC_STOP;
         if ((s->control_command = s->exec_command[SERVICE_EXEC_STOP])) {
+                s->control_command_id = SERVICE_EXEC_STOP;
+
                 if ((r = service_spawn(s,
                                        s->control_command,
                                        true,
@@ -1950,8 +1955,9 @@ static void service_enter_start_post(Service *s) {
 
         service_unwatch_control_pid(s);
 
-        s->control_command_id = SERVICE_EXEC_START_POST;
         if ((s->control_command = s->exec_command[SERVICE_EXEC_START_POST])) {
+                s->control_command_id = SERVICE_EXEC_START_POST;
+
                 if ((r = service_spawn(s,
                                        s->control_command,
                                        true,
@@ -1977,6 +1983,7 @@ fail:
 static void service_enter_start(Service *s) {
         pid_t pid;
         int r;
+        ExecCommand *c;
 
         assert(s);
 
@@ -1988,11 +1995,20 @@ static void service_enter_start(Service *s) {
         else
                 service_unwatch_main_pid(s);
 
-        s->control_command_id = SERVICE_EXEC_START;
-        s->control_command = s->exec_command[SERVICE_EXEC_START];
+        if (s->type == SERVICE_FORKING) {
+                s->control_command_id = SERVICE_EXEC_START;
+                c = s->control_command = s->exec_command[SERVICE_EXEC_START];
+
+                s->main_command = NULL;
+        } else {
+                s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
+                s->control_command = NULL;
+
+                c = s->main_command = s->exec_command[SERVICE_EXEC_START];
+        }
 
         if ((r = service_spawn(s,
-                               s->control_command,
+                               c,
                                s->type == SERVICE_FORKING || s->type == SERVICE_DBUS || s->type == SERVICE_NOTIFY,
                                true,
                                true,
@@ -2047,8 +2063,9 @@ static void service_enter_start_pre(Service *s) {
 
         service_unwatch_control_pid(s);
 
-        s->control_command_id = SERVICE_EXEC_START_PRE;
         if ((s->control_command = s->exec_command[SERVICE_EXEC_START_PRE])) {
+                s->control_command_id = SERVICE_EXEC_START_PRE;
+
                 if ((r = service_spawn(s,
                                        s->control_command,
                                        true,
@@ -2107,8 +2124,9 @@ static void service_enter_reload(Service *s) {
 
         service_unwatch_control_pid(s);
 
-        s->control_command_id = SERVICE_EXEC_RELOAD;
         if ((s->control_command = s->exec_command[SERVICE_EXEC_RELOAD])) {
+                s->control_command_id = SERVICE_EXEC_RELOAD;
+
                 if ((r = service_spawn(s,
                                        s->control_command,
                                        true,
@@ -2182,20 +2200,18 @@ static void service_run_next_main(Service *s, bool success) {
         int r;
 
         assert(s);
-        assert(s->control_command);
-        assert(s->control_command->command_next);
+        assert(s->main_command);
+        assert(s->main_command->command_next);
+        assert(s->type == SERVICE_ONESHOT);
 
         if (!success)
                 s->failure = true;
 
-        assert(s->control_command_id == SERVICE_EXEC_START);
-        assert(s->type == SERVICE_ONESHOT);
-
-        s->control_command = s->control_command->command_next;
+        s->main_command = s->main_command->command_next;
         service_unwatch_main_pid(s);
 
         if ((r = service_spawn(s,
-                               s->control_command,
+                               s->main_command,
                                false,
                                true,
                                true,
@@ -2510,10 +2526,14 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
                 s->main_pid = 0;
                 exec_status_exit(&s->main_exec_status, pid, code, status, s->exec_context.utmp_id);
 
-                if (s->type != SERVICE_FORKING && s->control_command) {
-                        s->control_command->exec_status = s->main_exec_status;
+                /* If this is not a forking service than the main
+                 * process got started and hence we copy the exit
+                 * status so that it is recorded both as main and as
+                 * control process exit status */
+                if (s->main_command) {
+                        s->main_command->exec_status = s->main_exec_status;
 
-                        if (s->control_command->ignore)
+                        if (s->main_command->ignore)
                                 success = true;
                 }
 
@@ -2521,8 +2541,8 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
                          "%s: main process exited, code=%s, status=%i", u->meta.id, sigchld_code_to_string(code), status);
                 s->failure = s->failure || !success;
 
-                if (s->control_command &&
-                    s->control_command->command_next &&
+                if (s->main_command &&
+                    s->main_command->command_next &&
                     success) {
 
                         /* There is another command to *
@@ -2535,9 +2555,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 
                         /* The service exited, so the service is officially
                          * gone. */
-
-                        s->control_command = NULL;
-                        s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
+                        s->main_command = NULL;
 
                         switch (s->state) {
 
diff --git a/src/service.h b/src/service.h
index 7586046..e06ff3d 100644
--- a/src/service.h
+++ b/src/service.h
@@ -103,10 +103,20 @@ struct Service {
 
         ServiceState state, deserialized_state;
 
+        /* The exit status of the real main process */
         ExecStatus main_exec_status;
 
+        /* The currently executed control process */
         ExecCommand *control_command;
+
+        /* The currently executed main process, which may be NULL if
+         * the main process got started via forking mode and not by
+         * us */
+        ExecCommand *main_command;
+
+        /* The ID of the control command currently being executed */
         ServiceExecCommand control_command_id;
+
         pid_t main_pid, control_pid;
         int socket_fd;
 

commit c06b7a15ea4bd9a6063eb16e1b4ee77ef05714b4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 20 18:44:06 2011 +0100

    service: don't allow reload operations for oneshot services
    
    During starting of oneshot we are in START state which we don't want to
    combine with the RELOAD state, hence we disallow both at the same time.

diff --git a/src/service.c b/src/service.c
index 4115e52..03a858a 100644
--- a/src/service.c
+++ b/src/service.c
@@ -1029,6 +1029,12 @@ static int service_verify(Service *s) {
                 return -EINVAL;
         }
 
+        if (s->type == SERVICE_ONESHOT &&
+            s->exec_command[SERVICE_EXEC_RELOAD]) {
+                log_error("%s has an ExecReload setting, which is not allowed for Type=oneshot services. Refusing.", s->meta.id);
+                return -EINVAL;
+        }
+
         if (s->type == SERVICE_DBUS && !s->bus_name) {
                 log_error("%s is of type D-Bus but no D-Bus service name has been specified. Refusing.", s->meta.id);
                 return -EINVAL;



More information about the systemd-commits mailing list