X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fsocket.c;h=a8f8dc3a5e834a98fdc88f972775c52b21abf772;hp=4443dba0c991b46a51cbd9140d26119127d0ac5c;hb=4ac9236fa14696db3e8a650a083a238eca9b9ae9;hpb=cae18e217208735797232eabb83a93470aefe88f diff --git a/src/socket.c b/src/socket.c index 4443dba0c..a8f8dc3a5 100644 --- a/src/socket.c +++ b/src/socket.c @@ -42,6 +42,7 @@ #include "bus-errors.h" #include "label.h" #include "exit-status.h" +#include "def.h" static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = { [SOCKET_DEAD] = UNIT_INACTIVE, @@ -67,7 +68,7 @@ static void socket_init(Unit *u) { s->backlog = SOMAXCONN; s->timeout_usec = DEFAULT_TIMEOUT_USEC; s->directory_mode = 0755; - s->socket_mode = 0666; + s->socket_mode = 0777; s->max_connections = 64; @@ -77,6 +78,8 @@ static void socket_init(Unit *u) { s->mark = -1; exec_context_init(&s->exec_context); + s->exec_context.std_output = u->meta.manager->default_std_output; + s->exec_context.std_error = u->meta.manager->default_std_error; s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID; } @@ -169,6 +172,13 @@ static int socket_instantiate_service(Socket *s) { if (r < 0) return r; +#ifdef HAVE_SYSV_COMPAT + if (SERVICE(u)->sysv_path) { + log_error("Using SysV services for socket activation is not supported. Refusing."); + return -ENOENT; + } +#endif + u->meta.no_gc = true; s->service = SERVICE(u); return 0; @@ -356,7 +366,10 @@ static int socket_load(Unit *u) { return socket_verify(s); } -static const char* listen_lookup(int type) { +static const char* listen_lookup(int family, int type) { + + if (family == AF_NETLINK) + return "ListenNetlink"; if (type == SOCK_STREAM) return "ListenStream"; @@ -467,7 +480,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { else t = k; - fprintf(f, "%s%s: %s\n", prefix, listen_lookup(p->address.type), t); + fprintf(f, "%s%s: %s\n", prefix, listen_lookup(socket_address_family(&p->address), p->address.type), t); free(k); } else fprintf(f, "%sListenFIFO: %s\n", prefix, p->path); @@ -1030,9 +1043,7 @@ static void socket_enter_signal(Socket *s, SocketState state, bool success) { int sig = (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_FINAL_SIGTERM) ? s->exec_context.kill_signal : SIGKILL; 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 (kill_and_sigcont(s->control_pid, sig) < 0 && errno != ESRCH) log_warning("Failed to kill control process %li: %m", (long) s->control_pid); else @@ -1051,13 +1062,14 @@ static void socket_enter_signal(Socket *s, SocketState state, bool success) { 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 = cgroup_bonding_kill_list(s->meta.cgroup_bondings, sig, true, 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); + pid_set = NULL; } } @@ -1189,6 +1201,8 @@ static void socket_enter_running(Socket *s, int cfd) { /* We don't take connections anymore if we are supposed to * shut down anyway */ if (unit_pending_inactive(UNIT(s))) { + log_debug("Suppressing connection request on %s since unit stop is scheduled.", s->meta.id); + if (cfd >= 0) close_nointr_nofail(cfd); else { @@ -1349,15 +1363,26 @@ static int socket_start(Unit *u) { /* Cannot run this without the service being around */ if (s->service) { - if (s->service->meta.load_state != UNIT_LOADED) + if (s->service->meta.load_state != UNIT_LOADED) { + log_error("Socket service %s not loaded, refusing.", s->service->meta.id); return -ENOENT; + } - /* If the service is alredy actvie we cannot start the + /* If the service is already active we cannot start the * socket */ if (s->service->state != SERVICE_DEAD && s->service->state != SERVICE_FAILED && - s->service->state != SERVICE_AUTO_RESTART) + s->service->state != SERVICE_AUTO_RESTART) { + log_error("Socket service %s already active, refusing.", s->service->meta.id); return -EBUSY; + } + +#ifdef HAVE_SYSV_COMPAT + if (s->service->sysv_path) { + log_error("Using SysV services for socket activation is not supported. Refusing."); + return -ENOENT; + } +#endif } assert(s->state == SOCKET_DEAD || s->state == SOCKET_FAILED); @@ -1429,7 +1454,10 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) { if ((r = socket_address_print(&p->address, &t)) < 0) return r; - unit_serialize_item_format(u, f, "socket", "%i %i %s", copy, p->address.type, t); + if (socket_address_family(&p->address) == AF_NETLINK) + unit_serialize_item_format(u, f, "netlink", "%i %s", copy, t); + else + unit_serialize_item_format(u, f, "socket", "%i %i %s", copy, p->address.type, t); free(t); } else { assert(p->type == SOCKET_FIFO); @@ -1524,6 +1552,25 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value, } } + } else if (streq(key, "netlink")) { + int fd, skip = 0; + SocketPort *p; + + if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd)) + log_debug("Failed to parse socket value %s", value); + else { + + LIST_FOREACH(port, p, s->ports) + if (socket_address_is_netlink(&p->address, value+skip)) + break; + + if (p) { + if (p->fd >= 0) + close_nointr_nofail(p->fd); + p->fd = fdset_remove(fds, fd); + } + } + } else log_debug("Unknown serialization key '%s'", key); @@ -1678,6 +1725,7 @@ static void socket_timer_event(Unit *u, uint64_t elapsed, Watch *w) { case SOCKET_START_PRE: log_warning("%s starting timed out. Terminating.", u->meta.id); socket_enter_signal(s, SOCKET_FINAL_SIGTERM, false); + break; case SOCKET_START_POST: log_warning("%s starting timed out. Stopping.", u->meta.id); @@ -1780,7 +1828,7 @@ void socket_connection_unref(Socket *s) { /* The service is dead. Yay! * - * This is strictly for one-onstance-per-connection + * This is strictly for one-instance-per-connection * services. */ assert(s->n_connections > 0); @@ -1818,7 +1866,7 @@ static int socket_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError } if (s->control_pid > 0) - if (kill(mode == KILL_PROCESS_GROUP ? -s->control_pid : s->control_pid, signo) < 0) + if (kill(s->control_pid, signo) < 0) r = -errno; if (mode == KILL_CONTROL_GROUP) { @@ -1834,7 +1882,7 @@ static int socket_kill(Unit *u, KillWho who, KillMode mode, int signo, DBusError goto finish; } - if ((q = cgroup_bonding_kill_list(s->meta.cgroup_bondings, signo, pid_set)) < 0) + if ((q = cgroup_bonding_kill_list(s->meta.cgroup_bondings, signo, false, pid_set)) < 0) if (r != -EAGAIN && r != -ESRCH && r != -ENOENT) r = q; }