chiark / gitweb /
core: notify triggered by socket of a service
authorUmut Tezduyar <umut@tezduyar.com>
Mon, 22 Jul 2013 08:52:53 +0000 (10:52 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 12 Sep 2013 16:47:20 +0000 (18:47 +0200)
TODO
src/core/service.c
src/core/socket.c
src/core/socket.h

diff --git a/TODO b/TODO
index 7f6defb8e5b0bbd45dd85a9b579905b4ddb093f5..0946ffaefb2a1efb06a0d23e987f1c9ee754f255 100644 (file)
--- a/TODO
+++ b/TODO
@@ -141,9 +141,6 @@ Features:
   Maybe take a BSD lock at the disk device node and teach udev to
   check for that and suppress event handling.
 
-* when a service changes state make reflect that in the
-  RUNNING/LISTENING states of its socket
-
 * when recursively showing the cgroup hierarchy, optionally also show
   the hierarchies of child processes
 
index 08b929e4fe7af4b5ff4763c7177b9e13ef9f0460..246a86e23f3cda577a46ee5d286e5051278c1695 100644 (file)
@@ -1489,24 +1489,6 @@ static int service_search_main_pid(Service *s) {
         return 0;
 }
 
-static void service_notify_sockets_dead(Service *s, bool failed_permanent) {
-        Iterator i;
-        Unit *u;
-
-        assert(s);
-
-        /* Notifies all our sockets when we die */
-
-        if (s->socket_fd >= 0)
-                return;
-
-        SET_FOREACH(u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY], i)
-                if (u->type == UNIT_SOCKET)
-                        socket_notify_service_dead(SOCKET(u), failed_permanent);
-
-        return;
-}
-
 static void service_set_state(Service *s, ServiceState state) {
         ServiceState old_state;
         const UnitActiveState *table;
@@ -1558,19 +1540,6 @@ static void service_set_state(Service *s, ServiceState state) {
                 s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
         }
 
-        if (state == SERVICE_FAILED)
-                service_notify_sockets_dead(s, s->result == SERVICE_FAILURE_START_LIMIT);
-
-        if (state == SERVICE_DEAD ||
-            state == SERVICE_STOP ||
-            state == SERVICE_STOP_SIGTERM ||
-            state == SERVICE_STOP_SIGKILL ||
-            state == SERVICE_STOP_POST ||
-            state == SERVICE_FINAL_SIGTERM ||
-            state == SERVICE_FINAL_SIGKILL ||
-            state == SERVICE_AUTO_RESTART)
-                service_notify_sockets_dead(s, false);
-
         if (state != SERVICE_START_PRE &&
             state != SERVICE_START &&
             state != SERVICE_START_POST &&
index cf88bae9da32147b86f570ffb4f89241ade14d53..2130e486865c686dcba251e861480bdda9b9efc2 100644 (file)
@@ -2277,7 +2277,7 @@ int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds) {
         return 0;
 }
 
-void socket_notify_service_dead(Socket *s, bool failed_permanent) {
+static void socket_notify_service_dead(Socket *s, bool failed_permanent) {
         assert(s);
 
         /* The service is dead. Dang!
@@ -2322,6 +2322,41 @@ static void socket_reset_failed(Unit *u) {
         s->result = SOCKET_SUCCESS;
 }
 
+static void socket_trigger_notify(Unit *u, Unit *other) {
+        Socket *s = SOCKET(u);
+        Service *se = SERVICE(other);
+
+        assert(u);
+        assert(other);
+
+        /* Don't propagate state changes from the service if we are
+           already down or accepting connections */
+        if ((s->state !=  SOCKET_RUNNING &&
+            s->state != SOCKET_LISTENING) ||
+            s->accept)
+                return;
+
+        if (other->load_state != UNIT_LOADED ||
+            other->type != UNIT_SERVICE)
+                return;
+
+        if (se->state == SERVICE_FAILED)
+                socket_notify_service_dead(s, se->result == SERVICE_FAILURE_START_LIMIT);
+
+        if (se->state == SERVICE_DEAD ||
+            se->state == SERVICE_STOP ||
+            se->state == SERVICE_STOP_SIGTERM ||
+            se->state == SERVICE_STOP_SIGKILL ||
+            se->state == SERVICE_STOP_POST ||
+            se->state == SERVICE_FINAL_SIGTERM ||
+            se->state == SERVICE_FINAL_SIGKILL ||
+            se->state == SERVICE_AUTO_RESTART)
+                socket_notify_service_dead(s, false);
+
+        if (se->state == SERVICE_RUNNING)
+                socket_set_state(s, SOCKET_RUNNING);
+}
+
 static int socket_kill(Unit *u, KillWho who, int signo, DBusError *error) {
         return unit_kill_common(u, who, signo, -1, SOCKET(u)->control_pid, error);
 }
@@ -2402,6 +2437,8 @@ const UnitVTable socket_vtable = {
         .sigchld_event = socket_sigchld_event,
         .timer_event = socket_timer_event,
 
+        .trigger_notify = socket_trigger_notify,
+
         .reset_failed = socket_reset_failed,
 
         .bus_interface = "org.freedesktop.systemd1.Socket",
index 8f9dfdbfb0f8c58300a3b7713320d834e207d59d..57333226f5f2565cae0a29800b8c3a09f1d6b279 100644 (file)
@@ -156,9 +156,6 @@ struct Socket {
 /* Called from the service code when collecting fds */
 int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds);
 
-/* Called from the service when it shut down */
-void socket_notify_service_dead(Socket *s, bool failed_permanent);
-
 /* Called from the mount code figure out if a mount is a dependency of
  * any of the sockets of this socket */
 int socket_add_one_mount_link(Socket *s, Mount *m);