chiark / gitweb /
util: replace close_nointr_nofail() by a more useful safe_close()
[elogind.git] / src / core / socket.c
index 31fc2a25269a659125ee42f284792e8040943af8..b2a3e954cbfd61a91fdb2bf3c281743f1f80d826 100644 (file)
@@ -96,6 +96,8 @@ static void socket_init(Unit *u) {
         kill_context_init(&s->kill_context);
         cgroup_context_init(&s->cgroup_context);
 
+        unit_cgroup_context_init_defaults(u, &s->cgroup_context);
+
         s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
 }
 
@@ -119,9 +121,7 @@ void socket_free_ports(Socket *s) {
 
                 sd_event_source_unref(p->event_source);
 
-                if (p->fd >= 0)
-                        close_nointr_nofail(p->fd);
-
+                safe_close(p->fd);
                 free(p->path);
                 free(p);
         }
@@ -175,11 +175,12 @@ static int socket_arm_timer(Socket *s) {
                 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
         }
 
-        return sd_event_add_monotonic(UNIT(s)->manager->event, now(CLOCK_MONOTONIC) + s->timeout_usec, 0, socket_dispatch_timer, s, &s->timer_event_source);
+        return sd_event_add_monotonic(UNIT(s)->manager->event, &s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec, 0, socket_dispatch_timer, s);
 }
 
 static int socket_instantiate_service(Socket *s) {
-        char *prefix, *name;
+        _cleanup_free_ char *prefix = NULL;
+        _cleanup_free_ char *name = NULL;
         int r;
         Unit *u;
 
@@ -195,18 +196,14 @@ static int socket_instantiate_service(Socket *s) {
 
         assert(s->accept);
 
-        if (!(prefix = unit_name_to_prefix(UNIT(s)->id)))
+        prefix = unit_name_to_prefix(UNIT(s)->id);
+        if (!prefix)
                 return -ENOMEM;
 
-        r = asprintf(&name, "%s@%u.service", prefix, s->n_accepted);
-        free(prefix);
-
-        if (r < 0)
+        if (asprintf(&name, "%s@%u.service", prefix, s->n_accepted) < 0)
                 return -ENOMEM;
 
         r = manager_load_unit(UNIT(s)->manager, name, NULL, NULL, &u);
-        free(name);
-
         if (r < 0)
                 return r;
 
@@ -339,7 +336,7 @@ static int socket_add_extras(Socket *s) {
         if (r < 0)
                 return r;
 
-        r = unit_exec_context_defaults(u, &s->exec_context);
+        r = unit_exec_context_patch_defaults(u, &s->exec_context);
         if (r < 0)
                 return r;
 
@@ -596,13 +593,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
 static int instance_from_socket(int fd, unsigned nr, char **instance) {
         socklen_t l;
         char *r;
-        union {
-                struct sockaddr sa;
-                struct sockaddr_un un;
-                struct sockaddr_in in;
-                struct sockaddr_in6 in6;
-                struct sockaddr_storage storage;
-        } local, remote;
+        union sockaddr_union local, remote;
 
         assert(fd >= 0);
         assert(instance);
@@ -671,10 +662,11 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
 
         case AF_UNIX: {
                 struct ucred ucred;
+                int k;
 
-                l = sizeof(ucred);
-                if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
-                        return -errno;
+                k = getpeercred(fd, &ucred);
+                if (k < 0)
+                        return k;
 
                 if (asprintf(&r,
                              "%u-%lu-%lu",
@@ -706,7 +698,7 @@ static void socket_close_fds(Socket *s) {
                 if (p->fd < 0)
                         continue;
 
-                close_nointr_nofail(p->fd);
+                p->fd = safe_close(p->fd);
 
                 /* One little note: we should never delete any sockets
                  * in the file system here! After all some other
@@ -715,8 +707,6 @@ static void socket_close_fds(Socket *s) {
                  * we delete sockets in the file system before we
                  * create a new one, not after we stopped using
                  * one! */
-
-                p->fd = -1;
         }
 }
 
@@ -886,9 +876,7 @@ static int fifo_address_create(
 
 fail:
         label_context_clear();
-
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        safe_close(fd);
 
         return r;
 }
@@ -923,8 +911,7 @@ static int special_address_create(
         return 0;
 
 fail:
-        if (fd >= 0)
-                close_nointr_nofail(fd);
+        safe_close(fd);
 
         return r;
 }
@@ -983,9 +970,7 @@ static int mq_address_create(
         return 0;
 
 fail:
-        if (fd >= 0)
-                close_nointr_nofail(fd);
-
+        safe_close(fd);
         return r;
 }
 
@@ -1112,7 +1097,7 @@ static int socket_watch_fds(Socket *s) {
                 if (p->event_source)
                         r = sd_event_source_set_enabled(p->event_source, SD_EVENT_ON);
                 else
-                        r = sd_event_add_io(UNIT(s)->manager->event, p->fd, EPOLLIN, socket_dispatch_io, p, &p->event_source);
+                        r = sd_event_add_io(UNIT(s)->manager->event, &p->event_source, p->fd, EPOLLIN, socket_dispatch_io, p);
 
                 if (r < 0) {
                         log_warning_unit(UNIT(s)->id, "Failed to watch listening fds: %s", strerror(-r));
@@ -1253,6 +1238,7 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
                        UNIT(s)->manager->confirm_spawn,
                        UNIT(s)->manager->cgroup_supported,
                        UNIT(s)->cgroup_path,
+                       manager_get_runtime_prefix(UNIT(s)->manager),
                        UNIT(s)->id,
                        0,
                        NULL,
@@ -1287,6 +1273,8 @@ static void socket_enter_dead(Socket *s, SocketResult f) {
         exec_runtime_destroy(s->exec_runtime);
         s->exec_runtime = exec_runtime_unref(s->exec_runtime);
 
+        exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager));
+
         socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD);
 }
 
@@ -1344,8 +1332,12 @@ static void socket_enter_signal(Socket *s, SocketState state, SocketResult f) {
                         goto fail;
 
                 socket_set_state(s, state);
-        } else if (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_STOP_PRE_SIGKILL)
+        } else if (state == SOCKET_STOP_PRE_SIGTERM)
+                socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, SOCKET_SUCCESS);
+        else if (state == SOCKET_STOP_PRE_SIGKILL)
                 socket_enter_stop_post(s, SOCKET_SUCCESS);
+        else if (state == SOCKET_FINAL_SIGTERM)
+                socket_enter_signal(s, SOCKET_FINAL_SIGKILL, SOCKET_SUCCESS);
         else
                 socket_enter_dead(s, SOCKET_SUCCESS);
 
@@ -1471,7 +1463,7 @@ static void socket_enter_running(Socket *s, int cfd) {
                 log_debug_unit(UNIT(s)->id, "Suppressing connection request on %s since unit stop is scheduled.", UNIT(s)->id);
 
                 if (cfd >= 0)
-                        close_nointr_nofail(cfd);
+                        safe_close(cfd);
                 else  {
                         /* Flush all sockets by closing and reopening them */
                         socket_close_fds(s);
@@ -1519,7 +1511,7 @@ static void socket_enter_running(Socket *s, int cfd) {
 
                 if (s->n_connections >= s->max_connections) {
                         log_warning_unit(UNIT(s)->id, "%s: Too many incoming connections (%u)", UNIT(s)->id, s->n_connections);
-                        close_nointr_nofail(cfd);
+                        safe_close(cfd);
                         return;
                 }
 
@@ -1534,7 +1526,7 @@ static void socket_enter_running(Socket *s, int cfd) {
 
                         /* ENOTCONN is legitimate if TCP RST was received.
                          * This connection is over, but the socket unit lives on. */
-                        close_nointr_nofail(cfd);
+                        safe_close(cfd);
                         return;
                 }
 
@@ -1585,9 +1577,7 @@ fail:
                          bus_error_message(&error, r));
 
         socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);
-
-        if (cfd >= 0)
-                close_nointr_nofail(cfd);
+        safe_close(cfd);
 }
 
 static void socket_run_next(Socket *s) {
@@ -1818,8 +1808,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                                         break;
 
                         if (p) {
-                                if (p->fd >= 0)
-                                        close_nointr_nofail(p->fd);
+                                safe_close(p->fd);
                                 p->fd = fdset_remove(fds, fd);
                         }
                 }
@@ -1838,8 +1827,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                                         break;
 
                         if (p) {
-                                if (p->fd >= 0)
-                                        close_nointr_nofail(p->fd);
+                                safe_close(p->fd);
                                 p->fd = fdset_remove(fds, fd);
                         }
                 }
@@ -1858,8 +1846,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                                         break;
 
                         if (p) {
-                                if (p->fd >= 0)
-                                        close_nointr_nofail(p->fd);
+                                safe_close(p->fd);
                                 p->fd = fdset_remove(fds, fd);
                         }
                 }
@@ -1877,8 +1864,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                                         break;
 
                         if (p) {
-                                if (p->fd >= 0)
-                                        close_nointr_nofail(p->fd);
+                                safe_close(p->fd);
                                 p->fd = fdset_remove(fds, fd);
                         }
                 }
@@ -1896,8 +1882,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
                                         break;
 
                         if (p) {
-                                if (p->fd >= 0)
-                                        close_nointr_nofail(p->fd);
+                                safe_close(p->fd);
                                 p->fd = fdset_remove(fds, fd);
                         }
                 }
@@ -2344,6 +2329,20 @@ static int socket_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
         return unit_kill_common(u, who, signo, -1, SOCKET(u)->control_pid, error);
 }
 
+static int socket_get_timeout(Unit *u, uint64_t *timeout) {
+        Socket *s = SOCKET(u);
+        int r;
+
+        if (!s->timer_event_source)
+                return 0;
+
+        r = sd_event_source_get_time(s->timer_event_source, timeout);
+        if (r < 0)
+                return r;
+
+        return 1;
+}
+
 static const char* const socket_state_table[_SOCKET_STATE_MAX] = {
         [SOCKET_DEAD] = "dead",
         [SOCKET_START_PRE] = "start-pre",
@@ -2408,6 +2407,8 @@ const UnitVTable socket_vtable = {
 
         .kill = socket_kill,
 
+        .get_timeout = socket_get_timeout,
+
         .serialize = socket_serialize,
         .deserialize_item = socket_deserialize_item,
         .distribute_fds = socket_distribute_fds,