chiark / gitweb /
service: consider a process exiting with SIGTERM a clean exit
[elogind.git] / socket.c
index 827d7b5e97600f5771a5b7d828782e8da650702d..259f2733cc6cafe2bbbbda6d9ddb8efeb025770a 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -119,9 +119,14 @@ static bool have_non_accept_socket(Socket *s) {
         if (!s->accept)
                 return true;
 
-        LIST_FOREACH(port, p, s->ports)
+        LIST_FOREACH(port, p, s->ports) {
+
+                if (p->type != SOCKET_SOCKET)
+                        return true;
+
                 if (!socket_address_can_accept(&p->address))
                         return true;
+        }
 
         return false;
 }
@@ -140,6 +145,79 @@ static int socket_verify(Socket *s) {
         return 0;
 }
 
+static bool socket_needs_mount(Socket *s, const char *prefix) {
+        SocketPort *p;
+
+        assert(s);
+
+        LIST_FOREACH(port, p, s->ports) {
+
+                if (p->type == SOCKET_SOCKET) {
+                        if (socket_address_needs_mount(&p->address, prefix))
+                                return true;
+                } else {
+                        assert(p->type == SOCKET_FIFO);
+                        if (path_startswith(p->path, prefix))
+                                return true;
+                }
+        }
+
+        return false;
+}
+
+int socket_add_one_mount_link(Socket *s, Mount *m) {
+        int r;
+
+        assert(s);
+        assert(m);
+
+        if (s->meta.load_state != UNIT_LOADED ||
+            m->meta.load_state != UNIT_LOADED)
+                return 0;
+
+        if (!socket_needs_mount(s, m->where))
+                return 0;
+
+        if ((r = unit_add_dependency(UNIT(m), UNIT_BEFORE, UNIT(s), true)) < 0)
+                return r;
+
+        if ((r = unit_add_dependency(UNIT(s), UNIT_REQUIRES, UNIT(m), true)) < 0)
+                return r;
+
+        return 0;
+}
+
+static int socket_add_mount_links(Socket *s) {
+        Meta *other;
+        int r;
+
+        assert(s);
+
+        LIST_FOREACH(units_per_type, other, s->meta.manager->units_per_type[UNIT_MOUNT])
+                if ((r = socket_add_one_mount_link(s, (Mount*) other)) < 0)
+                        return r;
+
+        return 0;
+}
+
+static int socket_add_device_link(Socket *s) {
+        char *t;
+        int r;
+
+        assert(s);
+
+        if (!s->bind_to_device)
+                return 0;
+
+        if (asprintf(&t, "/sys/subsystem/net/devices/%s", s->bind_to_device) < 0)
+                return -ENOMEM;
+
+        r = unit_add_node_link(UNIT(s), t, false);
+        free(t);
+
+        return r;
+}
+
 static int socket_load(Unit *u) {
         Socket *s = SOCKET(u);
         int r;
@@ -161,6 +239,12 @@ static int socket_load(Unit *u) {
                                 return r;
                 }
 
+                if ((r = socket_add_mount_links(s)) < 0)
+                        return r;
+
+                if ((r = socket_add_device_link(s)) < 0)
+                        return r;
+
                 if ((r = unit_add_exec_dependencies(u, &s->exec_context)) < 0)
                         return r;
 
@@ -448,8 +532,9 @@ static int socket_watch_fds(Socket *s) {
                 if (p->fd < 0)
                         continue;
 
-                p->fd_watch.data.socket_accept =
+                p->fd_watch.socket_accept =
                         s->accept &&
+                        p->type == SOCKET_SOCKET &&
                         socket_address_can_accept(&p->address);
 
                 if ((r = unit_watch_fd(UNIT(s), p->fd, EPOLLIN, &p->fd_watch)) < 0)
@@ -572,6 +657,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
                        argv,
                        &s->exec_context,
                        NULL, 0,
+                       s->meta.manager->environment,
                        true,
                        true,
                        UNIT(s)->meta.manager->confirm_spawn,
@@ -661,7 +747,7 @@ static void socket_enter_signal(Socket *s, SocketState state, bool success) {
                         }
         }
 
-        if (sent) {
+        if (sent && s->control_pid > 0) {
                 if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
                         goto fail;
 
@@ -1088,7 +1174,7 @@ static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
                 goto fail;
         }
 
-        if (w->data.socket_accept) {
+        if (w->socket_accept) {
                 for (;;) {
 
                         if ((cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK)) < 0) {
@@ -1104,7 +1190,6 @@ static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
                 }
         }
 
-        log_debug("cfd=%i", cfd);
         socket_enter_running(s, cfd);
         return;
 
@@ -1119,7 +1204,7 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         assert(s);
         assert(pid >= 0);
 
-        success = code == CLD_EXITED && status == 0;
+        success = is_clean_exit(code, status);
         s->failure = s->failure || !success;
 
         assert(s->control_pid == pid);