chiark / gitweb /
socket: don't allow mixing of accepting and non-accepting sockets in the same unit
[elogind.git] / src / socket.c
index 7ff2927aff984152251ffd5de28895bf77c822e0..78fc049a95773cf7af9615ff07076711144e95b1 100644 (file)
@@ -160,6 +160,11 @@ static int socket_verify(Socket *s) {
                 return -EINVAL;
         }
 
+        if (s->accept && have_non_accept_socket(s)) {
+                log_error("%s configured for accepting sockets, but sockets are non-accepting. Refusing.", s->meta.id);
+                return -EINVAL;
+        }
+
         if (s->accept && s->max_connections <= 0) {
                 log_error("%s's MaxConnection setting too small. Refusing.", s->meta.id);
                 return -EINVAL;
@@ -1030,6 +1035,24 @@ static void socket_enter_running(Socket *s, int cfd) {
         assert(s);
         dbus_error_init(&error);
 
+        /* We don't take connections anymore if we are supposed to
+         * shut down anyway */
+        if (s->meta.job && s->meta.job->type == JOB_STOP) {
+                if (cfd >= 0)
+                        close_nointr_nofail(cfd);
+                else  {
+                        /* Flush all sockets by closing and reopening them */
+                        socket_close_fds(s);
+
+                        if ((r = socket_watch_fds(s)) < 0) {
+                                log_warning("%s failed to watch sockets: %s", s->meta.id, strerror(-r));
+                                socket_enter_stop_pre(s, false);
+                        }
+                }
+
+                return;
+        }
+
         if (cfd < 0) {
                 if ((r = manager_add_job(s->meta.manager, JOB_START, UNIT(s->service), JOB_REPLACE, true, &error, NULL)) < 0)
                         goto fail;
@@ -1400,12 +1423,16 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         s->control_pid = 0;
 
         success = is_clean_exit(code, status);
-        s->failure = s->failure || !success;
 
-        if (s->control_command)
+        if (s->control_command) {
                 exec_status_exit(&s->control_command->exec_status, pid, code, status);
 
+                if (s->control_command->ignore)
+                        success = true;
+        }
+
         log_debug("%s control 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 && success) {
                 log_debug("%s running next command for state %s", u->meta.id, socket_state_to_string(s->state));