chiark / gitweb /
cgroup: if we do a cgroup operation then do something on all supported controllers
[elogind.git] / src / core / socket.c
index c1bbaec4477402f9eae3a5d29571dd40387155f1..190b36c3cab4477d8e8b5c6e8c3b02b1f17c3425 100644 (file)
@@ -536,6 +536,11 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                         "%sMessageQueueMessageSize: %li\n",
                         prefix, s->mq_msgsize);
 
+        if (s->reuseport)
+                fprintf(f,
+                        "%sReusePort: %s\n",
+                         prefix, yes_no(s->reuseport));
+
         if (s->smack)
                 fprintf(f,
                         "%sSmackLabel: %s\n",
@@ -792,6 +797,12 @@ static void socket_apply_socket_options(Socket *s, int fd) {
                 if (setsockopt(fd, SOL_TCP, TCP_CONGESTION, s->tcp_congestion, strlen(s->tcp_congestion)+1) < 0)
                         log_warning_unit(UNIT(s)->id, "TCP_CONGESTION failed: %m");
 
+        if (s->reuseport) {
+                int b = s->reuseport;
+                if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &b, sizeof(b)))
+                        log_warning_unit(UNIT(s)->id, "SO_REUSEPORT failed: %m");
+        }
+
 #ifdef HAVE_SMACK
         if (s->smack_ip_in)
                 if (fsetxattr(fd, "security.SMACK64IPIN", s->smack_ip_in, strlen(s->smack_ip_in), 0) < 0)
@@ -1215,11 +1226,9 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
         if (r < 0)
                 goto fail;
 
-        argv = unit_full_printf_strv(UNIT(s), c->argv);
-        if (!argv) {
-                r = -ENOMEM;
+        r = unit_full_printf_strv(UNIT(s), c->argv, &argv);
+        if (r < 0)
                 goto fail;
-        }
 
         r = exec_spawn(c,
                        argv,
@@ -1230,7 +1239,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
                        true,
                        true,
                        UNIT(s)->manager->confirm_spawn,
-                       UNIT(s)->cgroup_mask,
+                       UNIT(s)->manager->cgroup_supported,
                        UNIT(s)->cgroup_path,
                        UNIT(s)->id,
                        NULL,
@@ -2266,7 +2275,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!
@@ -2311,6 +2320,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);
 }
@@ -2391,11 +2435,15 @@ 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",
         .bus_message_handler = bus_socket_message_handler,
         .bus_invalidating_properties =  bus_socket_invalidating_properties,
+        .bus_set_property = bus_socket_set_property,
+        .bus_commit_properties = bus_socket_commit_properties,
 
         .status_message_formats = {
                 /*.starting_stopping = {