s->ip_ttl = -1;
s->mark = -1;
- exec_context_init(&s->exec_context);
s->exec_context.std_output = u->manager->default_std_output;
s->exec_context.std_error = u->manager->default_std_error;
- kill_context_init(&s->kill_context);
- cgroup_context_init(&s->cgroup_context);
s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
}
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);
}
socket_free_ports(s);
- cgroup_context_done(&s->cgroup_context);
- exec_context_done(&s->exec_context);
s->exec_runtime = exec_runtime_unref(s->exec_runtime);
exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX);
s->control_command = NULL;
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_time(
+ UNIT(s)->manager->event,
+ &s->timer_event_source,
+ CLOCK_MONOTONIC,
+ 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;
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;
if (r < 0)
return r;
- r = unit_exec_context_defaults(u, &s->exec_context);
+ r = unit_patch_contexts(u);
if (r < 0)
return r;
if (r < 0)
return r;
- r = unit_add_default_slice(u);
+ r = unit_add_default_slice(u, &s->cgroup_context);
if (r < 0)
return r;
}
if (s->control_pid > 0)
fprintf(f,
- "%sControl PID: %lu\n",
- prefix, (unsigned long) s->control_pid);
+ "%sControl PID: "PID_FMT"\n",
+ prefix, s->control_pid);
if (s->bind_to_device)
fprintf(f,
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);
case AF_UNIX: {
struct ucred ucred;
+ int k;
- l = sizeof(ucred);
- if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
- return -errno;
-
- if (asprintf(&r,
- "%u-%lu-%lu",
- nr,
- (unsigned long) ucred.pid,
- (unsigned long) ucred.uid) < 0)
- return -ENOMEM;
+ k = getpeercred(fd, &ucred);
+ if (k >= 0) {
+ if (asprintf(&r,
+ "%u-"PID_FMT"-"UID_FMT,
+ nr, ucred.pid, ucred.uid) < 0)
+ return -ENOMEM;
+ } else if (k == -ENODATA) {
+ /* This handles the case where somebody is
+ * connecting from another pid/uid namespace
+ * (e.g. from outside of our container). */
+ if (asprintf(&r,
+ "%u-unknown",
+ nr) < 0)
+ return -ENOMEM;
+ } else
+ return k;
break;
}
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
* we delete sockets in the file system before we
* create a new one, not after we stopped using
* one! */
-
- p->fd = -1;
}
}
fail:
label_context_clear();
-
- if (fd >= 0)
- close_nointr_nofail(fd);
+ safe_close(fd);
return r;
}
return 0;
fail:
- if (fd >= 0)
- close_nointr_nofail(fd);
+ safe_close(fd);
return r;
}
return 0;
fail:
- if (fd >= 0)
- close_nointr_nofail(fd);
-
+ safe_close(fd);
return r;
}
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));
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,
s->exec_runtime,
&pid);
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);
}
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);
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);
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;
}
/* 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;
}
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) {
unit_serialize_item_format(u, f, "n-accepted", "%u", s->n_accepted);
if (s->control_pid > 0)
- unit_serialize_item_format(u, f, "control-pid", "%lu", (unsigned long) s->control_pid);
+ unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid);
if (s->control_command_id >= 0)
unit_serialize_item(u, f, "control-command", socket_exec_command_to_string(s->control_command_id));
break;
if (p) {
- if (p->fd >= 0)
- close_nointr_nofail(p->fd);
+ safe_close(p->fd);
p->fd = fdset_remove(fds, fd);
}
}
break;
if (p) {
- if (p->fd >= 0)
- close_nointr_nofail(p->fd);
+ safe_close(p->fd);
p->fd = fdset_remove(fds, fd);
}
}
break;
if (p) {
- if (p->fd >= 0)
- close_nointr_nofail(p->fd);
+ safe_close(p->fd);
p->fd = fdset_remove(fds, fd);
}
}
break;
if (p) {
- if (p->fd >= 0)
- close_nointr_nofail(p->fd);
+ safe_close(p->fd);
p->fd = fdset_remove(fds, fd);
}
}
break;
if (p) {
- if (p->fd >= 0)
- close_nointr_nofail(p->fd);
+ safe_close(p->fd);
p->fd = fdset_remove(fds, fd);
}
}
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",
.kill = socket_kill,
+ .get_timeout = socket_get_timeout,
+
.serialize = socket_serialize,
.deserialize_item = socket_deserialize_item,
.distribute_fds = socket_distribute_fds,