X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fsocket.c;h=aacf9bed9f1f50f106db3cd78b322461fc689ef8;hb=dd36de4d520fc77f0e2ea83f560040d36be3ee50;hp=7510a6d6decd7eaedd57b9dc9bb907ffbc535116;hpb=c4e2ceae941d02de5574becbfd3b4db15de2eda3;p=elogind.git diff --git a/src/socket.c b/src/socket.c index 7510a6d6d..aacf9bed9 100644 --- a/src/socket.c +++ b/src/socket.c @@ -54,7 +54,7 @@ static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = { [SOCKET_STOP_POST] = UNIT_DEACTIVATING, [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING, [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING, - [SOCKET_MAINTENANCE] = UNIT_MAINTENANCE + [SOCKET_FAILED] = UNIT_FAILED }; static void socket_init(Unit *u) { @@ -385,7 +385,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { prefix, s->directory_mode, prefix, yes_no(s->keep_alive), prefix, yes_no(s->free_bind), - prefix, s->tcp_congestion); + prefix, strna(s->tcp_congestion)); if (s->control_pid > 0) fprintf(f, @@ -634,7 +634,13 @@ static void socket_apply_socket_options(Socket *s, int fd) { int r, x; r = setsockopt(fd, IPPROTO_IP, IP_TTL, &s->ip_ttl, sizeof(s->ip_ttl)); - x = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &s->ip_ttl, sizeof(s->ip_ttl)); + + if (socket_ipv6_is_supported()) + x = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &s->ip_ttl, sizeof(s->ip_ttl)); + else { + x = -1; + errno = EAFNOSUPPORT; + } if (r < 0 && x < 0) log_warning("IP_TTL/IPV6_UNICAST_HOPS failed: %m"); @@ -724,15 +730,10 @@ static int socket_open_fds(Socket *s) { SocketPort *p; int r; char *label = NULL; + bool know_label = false; assert(s); - if ((r = socket_instantiate_service(s)) < 0) - return r; - - if ((r = label_get_socket_label_from_exe(s->service->exec_command[SERVICE_EXEC_START]->path, &label)) < 0) - return r; - LIST_FOREACH(port, p, s->ports) { if (p->fd >= 0) @@ -740,6 +741,17 @@ static int socket_open_fds(Socket *s) { if (p->type == SOCKET_SOCKET) { + if (!know_label) { + + if ((r = socket_instantiate_service(s)) < 0) + return r; + + if ((r = label_get_socket_label_from_exe(s->service->exec_command[SERVICE_EXEC_START]->path, &label)) < 0) + return r; + + know_label = true; + } + if ((r = socket_address_listen( &p->address, s->backlog, @@ -760,7 +772,6 @@ static int socket_open_fds(Socket *s) { p->path, s->directory_mode, s->socket_mode, - label, &p->fd)) < 0) goto rollback; @@ -959,7 +970,7 @@ static void socket_enter_dead(Socket *s, bool success) { if (!success) s->failure = true; - socket_set_state(s, s->failure ? SOCKET_MAINTENANCE : SOCKET_DEAD); + socket_set_state(s, s->failure ? SOCKET_FAILED : SOCKET_DEAD); } static void socket_enter_signal(Socket *s, SocketState state, bool success); @@ -992,7 +1003,8 @@ fail: static void socket_enter_signal(Socket *s, SocketState state, bool success) { int r; - bool sent = false; + Set *pid_set = NULL; + bool wait_for_exit = false; assert(s); @@ -1002,23 +1014,39 @@ static void socket_enter_signal(Socket *s, SocketState state, bool success) { if (s->exec_context.kill_mode != KILL_NONE) { int sig = (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_FINAL_SIGTERM) ? s->exec_context.kill_signal : SIGKILL; - if (s->exec_context.kill_mode == KILL_CONTROL_GROUP) { + if (s->control_pid > 0) { + if (kill(s->exec_context.kill_mode == KILL_PROCESS_GROUP ? + -s->control_pid : + s->control_pid, sig) < 0 && errno != ESRCH) - if ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig)) < 0) { - if (r != -EAGAIN && r != -ESRCH) - goto fail; - } else - sent = true; + log_warning("Failed to kill control process %li: %m", (long) s->control_pid); + else + wait_for_exit = true; } - if (!sent && s->control_pid > 0) - if (kill(s->exec_context.kill_mode == KILL_PROCESS ? s->control_pid : -s->control_pid, sig) < 0 && errno != ESRCH) { - r = -errno; + if (s->exec_context.kill_mode == KILL_CONTROL_GROUP) { + + if (!(pid_set = set_new(trivial_hash_func, trivial_compare_func))) { + r = -ENOMEM; goto fail; } + + /* Exclude the control pid from being killed via the cgroup */ + if (s->control_pid > 0) + if ((r = set_put(pid_set, LONG_TO_PTR(s->control_pid))) < 0) + goto fail; + + if ((r = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig, pid_set)) < 0) { + if (r != -EAGAIN && r != -ESRCH && r != -ENOENT) + log_warning("Failed to kill control group: %s", strerror(-r)); + } else if (r > 0) + wait_for_exit = true; + + set_free(pid_set); + } } - if (sent && s->control_pid > 0) { + if (wait_for_exit) { if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0) goto fail; @@ -1037,6 +1065,9 @@ fail: socket_enter_stop_post(s, false); else socket_enter_dead(s, false); + + if (pid_set) + set_free(pid_set); } static void socket_enter_stop_pre(Socket *s, bool success) { @@ -1142,7 +1173,7 @@ static void socket_enter_running(Socket *s, int cfd) { /* 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 (unit_pending_inactive(UNIT(s))) { if (cfd >= 0) close_nointr_nofail(cfd); else { @@ -1290,12 +1321,12 @@ static int socket_start(Unit *u) { /* If the service is alredy actvie we cannot start the * socket */ if (s->service->state != SERVICE_DEAD && - s->service->state != SERVICE_MAINTENANCE && + s->service->state != SERVICE_FAILED && s->service->state != SERVICE_AUTO_RESTART) return -EBUSY; } - assert(s->state == SOCKET_DEAD || s->state == SOCKET_MAINTENANCE); + assert(s->state == SOCKET_DEAD || s->state == SOCKET_FAILED); s->failure = false; socket_enter_start_pre(s); @@ -1645,7 +1676,7 @@ static void socket_timer_event(Unit *u, uint64_t elapsed, Watch *w) { break; case SOCKET_FINAL_SIGKILL: - log_warning("%s still around after SIGKILL (2). Entering maintenance mode.", u->meta.id); + log_warning("%s still around after SIGKILL (2). Entering failed mode.", u->meta.id); socket_enter_dead(s, false); break; @@ -1714,12 +1745,12 @@ void socket_connection_unref(Socket *s) { log_debug("%s: One connection closed, %u left.", s->meta.id, s->n_connections); } -static void socket_reset_maintenance(Unit *u) { +static void socket_reset_failed(Unit *u) { Socket *s = SOCKET(u); assert(s); - if (s->state == SOCKET_MAINTENANCE) + if (s->state == SOCKET_FAILED) socket_set_state(s, SOCKET_DEAD); s->failure = false; @@ -1737,7 +1768,7 @@ static const char* const socket_state_table[_SOCKET_STATE_MAX] = { [SOCKET_STOP_POST] = "stop-post", [SOCKET_FINAL_SIGTERM] = "final-sigterm", [SOCKET_FINAL_SIGKILL] = "final-sigkill", - [SOCKET_MAINTENANCE] = "maintenance" + [SOCKET_FAILED] = "failed" }; DEFINE_STRING_TABLE_LOOKUP(socket_state, SocketState); @@ -1777,7 +1808,7 @@ const UnitVTable socket_vtable = { .sigchld_event = socket_sigchld_event, .timer_event = socket_timer_event, - .reset_maintenance = socket_reset_maintenance, + .reset_failed = socket_reset_failed, .bus_interface = "org.freedesktop.systemd1.Socket", .bus_message_handler = bus_socket_message_handler,