socket.c revision 21b735e798c580e7af8c33ace9f8565860b7f8df
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering This file is part of systemd.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Copyright 2010 Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is free software; you can redistribute it and/or modify it
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering under the terms of the GNU Lesser General Public License as published by
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering (at your option) any later version.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is distributed in the hope that it will be useful, but
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Lesser General Public License for more details.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering You should have received a copy of the GNU Lesser General Public License
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering [SOCKET_STOP_PRE_SIGTERM] = UNIT_DEACTIVATING,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering [SOCKET_STOP_PRE_SIGKILL] = UNIT_DEACTIVATING,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering [SOCKET_FINAL_SIGTERM] = UNIT_DEACTIVATING,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering [SOCKET_FINAL_SIGKILL] = UNIT_DEACTIVATING,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering s->timeout_usec = u->manager->default_timeout_start_usec;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering s->exec_context.std_output = u->manager->default_std_output;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering s->exec_context.std_error = u->manager->default_std_error;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering s->control_command_id = _SOCKET_EXEC_COMMAND_INVALID;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic void socket_unwatch_control_pid(Socket *s) {
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering unit_unwatch_pid(UNIT(s), s->control_pid);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering while ((p = s->ports)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering s->exec_runtime = exec_runtime_unref(s->exec_runtime);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering s->timer_event_source = sd_event_source_unref(s->timer_event_source);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering s->timer_event_source = sd_event_source_unref(s->timer_event_source);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering now(CLOCK_MONOTONIC) + s->timeout_usec, 0,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering (void) sd_event_source_set_description(s->timer_event_source, "socket-timer");
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmekint socket_instantiate_service(Socket *s) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_free_ char *prefix = NULL, *name = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* This fills in s->service if it isn't filled in yet. For
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering * Accept=yes sockets we create the next connection service
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering * here. For Accept=no this is mostly a NOP since the service
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering * is figured out at load time anyway. */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = unit_name_to_prefix(UNIT(s)->id, &prefix);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (asprintf(&name, "%s@%u.service", prefix, s->n_accepted) < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = manager_load_unit(UNIT(s)->manager, name, NULL, NULL, &u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, u, false);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic bool have_non_accept_socket(Socket *s) {
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek if (!socket_address_can_accept(&p->address))
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poetteringstatic int socket_add_mount_links(Socket *s) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering path = socket_address_get_path(&p->address);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering else if (p->type == SOCKET_FIFO || p->type == SOCKET_SPECIAL)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = unit_require_mounts_for(UNIT(s), path);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poetteringstatic int socket_add_device_link(Socket *s) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (!s->bind_to_device || streq(s->bind_to_device, "lo"))
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering t = strjoina("/sys/subsystem/net/devices/", s->bind_to_device);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return unit_add_node_link(UNIT(s), t, false);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poetteringstatic int socket_add_default_dependencies(Socket *s) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = unit_add_dependency_by_name(UNIT(s), UNIT_BEFORE, SPECIAL_SOCKETS_TARGET, NULL, true);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (UNIT(s)->manager->running_as == MANAGER_SYSTEM) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering_pure_ static bool socket_has_exec(Socket *s) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering for (i = 0; i < _SOCKET_EXEC_COMMAND_MAX; i++)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = unit_load_related_unit(u, ".service", &x);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(s->service), true);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = unit_add_exec_dependencies(u, &s->exec_context);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = unit_add_default_slice(u, &s->cgroup_context);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic const char *socket_find_symlink_target(Socket *s) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering const char *f = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (p->address.sockaddr.un.sun_path[0] != 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_unit_error(UNIT(s), "Unit lacks Listen setting. Refusing.");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (s->accept && have_non_accept_socket(s)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_unit_error(UNIT(s), "Unit configured for accepting sockets, but sockets are non-accepting. Refusing.");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (s->accept && s->max_connections <= 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_unit_error(UNIT(s), "MaxConnection= setting too small. Refusing.");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (s->accept && UNIT_DEREF(s->service)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_unit_error(UNIT(s), "Explicit service configuration for accepting socket units not supported. Refusing.");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (s->exec_context.pam_name && s->kill_context.kill_mode != KILL_CONTROL_GROUP) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_unit_error(UNIT(s), "Unit has PAM enabled. Kill mode must be set to 'control-group'. Refusing.");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!strv_isempty(s->symlinks) && !socket_find_symlink_target(s)) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_unit_error(UNIT(s), "Unit has symlinks set but none or more than one node in the file system. Refusing.");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* This is a new unit? Then let's add in some extras */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering_const_ static const char* listen_lookup(int family, int type) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return "ListenNetlink";
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return "ListenStream";
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return "ListenDatagram";
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return "ListenSequentialPacket";
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert_not_reached("Unknown socket type");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic void socket_dump(Unit *u, FILE *f, const char *prefix) {
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering "%sSocket State: %s\n"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering "%sResult: %s\n"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering "%sBindIPv6Only: %s\n"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering "%sBacklog: %u\n"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering "%sSocketMode: %04o\n"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering "%sDirectoryMode: %04o\n"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering "%sKeepAlive: %s\n"
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering "%sNoDelay: %s\n"
if (s->control_pid > 0)
fprintf(f,
if (s->bind_to_device)
fprintf(f,
if (s->accept)
fprintf(f,
if (s->priority >= 0)
fprintf(f,
if (s->receive_buffer > 0)
fprintf(f,
if (s->send_buffer > 0)
fprintf(f,
if (s->ip_tos >= 0)
fprintf(f,
if (s->ip_ttl >= 0)
fprintf(f,
if (s->pipe_size > 0)
fprintf(f,
if (s->mark >= 0)
fprintf(f,
if (s->mq_maxmsg > 0)
fprintf(f,
if (s->mq_msgsize > 0)
fprintf(f,
if (s->reuse_port)
fprintf(f,
if (s->smack)
fprintf(f,
if (s->smack_ip_in)
fprintf(f,
if (s->smack_ip_out)
fprintf(f,
fprintf(f,
if (s->keep_alive_time > 0)
fprintf(f,
if (s->keep_alive_interval)
fprintf(f,
if (s->keep_alive_cnt)
fprintf(f,
if (s->defer_accept)
fprintf(f,
char *k = NULL;
t = strerror(-r);
fprintf(f, "%s%s: %s\n", prefix, listen_lookup(socket_address_family(&p->address), p->address.type), t);
free(k);
for (c = 0; c < _SOCKET_EXEC_COMMAND_MAX; c++) {
if (!s->exec_command[c])
socklen_t l;
l = sizeof(local);
return -errno;
l = sizeof(remote);
return -errno;
case AF_INET: {
if (asprintf(&r,
nr,
return -ENOMEM;
case AF_INET6: {
static const unsigned char ipv4_prefix[] = {
const uint8_t
if (asprintf(&r,
nr,
return -ENOMEM;
if (asprintf(&r,
nr,
return -ENOMEM;
case AF_UNIX: {
if (asprintf(&r,
return -ENOMEM;
} else if (k == -ENODATA) {
if (asprintf(&r,
nr) < 0)
return -ENOMEM;
*instance = r;
SocketPort *p;
assert(s);
if (p->fd < 0)
if (s->remove_on_stop) {
switch (p->type) {
case SOCKET_FIFO:
case SOCKET_MQUEUE:
case SOCKET_SOCKET:
if (s->remove_on_stop)
unlink(*i);
assert(s);
if (s->keep_alive) {
int b = s->keep_alive;
if (s->keep_alive_time) {
if (s->keep_alive_interval) {
if (s->keep_alive_cnt) {
if (s->defer_accept) {
if (s->no_delay) {
int b = s->no_delay;
if (s->broadcast) {
if (s->pass_cred) {
if (s->pass_sec) {
if (s->priority >= 0)
if (s->receive_buffer > 0) {
if (s->send_buffer > 0) {
if (s->mark >= 0)
if (s->ip_tos >= 0)
if (s->ip_ttl >= 0) {
if (socket_ipv6_is_supported())
if (s->tcp_congestion)
if (s->smack_ip_in) {
if (s->smack_ip_out) {
assert(s);
if (s->pipe_size > 0)
if (s->smack) {
static int fifo_address_create(
const char *path,
int *_fd) {
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -EEXIST;
goto fail;
fail:
static int special_address_create(
const char *path,
int *_fd) {
if (fd < 0) {
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -EEXIST;
goto fail;
fail:
static int mq_address_create(
const char *path,
long maxmsg,
long msgsize,
int *_fd) {
if (fd < 0) {
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -EEXIST;
goto fail;
fail:
assert(s);
p = socket_find_symlink_target(s);
symlink_label(p, *i);
SocketPort *p;
bool know_label = false;
assert(s);
if (p->fd >= 0)
if (!know_label) {
if (s->selinux_context_from_net) {
if (r < 0 && r != -EOPNOTSUPP)
goto rollback;
r = socket_instantiate_service(s);
goto rollback;
r = mac_selinux_get_create_label_from_exe(SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START]->path, &label);
goto rollback;
know_label = true;
&p->address,
s->backlog,
s->bind_ipv6_only,
s->bind_to_device,
s->reuse_port,
s->free_bind,
s->transparent,
s->directory_mode,
s->socket_mode,
label);
goto rollback;
p->fd = r;
socket_symlink(s);
p->path,
&p->fd);
goto rollback;
r = fifo_address_create(
p->path,
s->directory_mode,
s->socket_mode,
&p->fd);
goto rollback;
socket_symlink(s);
r = mq_address_create(
p->path,
s->socket_mode,
s->mq_maxmsg,
s->mq_msgsize,
&p->fd);
goto rollback;
socket_close_fds(s);
SocketPort *p;
assert(s);
if (p->fd < 0)
if (!p->event_source)
SocketPort *p;
assert(s);
if (p->fd < 0)
if (p->event_source) {
goto fail;
r = sd_event_add_io(UNIT(s)->manager->event, &p->event_source, p->fd, EPOLLIN, socket_dispatch_io, p);
goto fail;
fail:
assert(s);
socket_close_fds(s);
log_unit_debug(UNIT(s), "Changed %s -> %s", socket_state_to_string(old_state), socket_state_to_string(state));
assert(s);
if (s->control_pid <= 0)
return -EBADMSG;
r = socket_arm_timer(s);
r = socket_open_fds(s);
r = socket_watch_fds(s);
.apply_permissions = true,
.apply_chroot = true,
.apply_tty_stdin = true,
assert(s);
assert(c);
if (s->reset_cpu_usage) {
s->reset_cpu_usage = false;
goto fail;
r = socket_arm_timer(s);
goto fail;
goto fail;
&s->exec_context,
s->exec_runtime,
&pid);
goto fail;
goto fail;
fail:
r = socket_arm_timer(s);
goto fail;
if (pid < 0)
return -errno;
if (pid == 0) {
SocketPort *p;
int ret;
goto fail_child;
goto fail_child;
if (!path)
r = -errno;
goto fail_child;
_exit(0);
log_open();
log_error_errno(r, "Failed to chown socket at step %s: %m", exit_status_to_string(ret, EXIT_STATUS_SYSTEMD));
goto fail;
fail:
assert(s);
if (f != SOCKET_SUCCESS)
s->result = f;
exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager));
assert(s);
if (f != SOCKET_SUCCESS)
s->result = f;
if (s->control_command) {
goto fail;
fail:
assert(s);
if (f != SOCKET_SUCCESS)
s->result = f;
r = unit_kill_context(
UNIT(s),
&s->kill_context,
s->control_pid,
goto fail;
r = socket_arm_timer(s);
goto fail;
fail:
assert(s);
if (f != SOCKET_SUCCESS)
s->result = f;
if (s->control_command) {
goto fail;
fail:
assert(s);
r = socket_watch_fds(s);
goto fail;
fail:
assert(s);
if (s->control_command) {
goto fail;
fail:
assert(s);
r = socket_open_fds(s);
goto fail;
goto fail;
fail:
assert(s);
if (s->control_command) {
goto fail;
fail:
assert(s);
if (cfd >= 0)
socket_close_fds(s);
r = socket_open_fds(s);
r = socket_watch_fds(s);
if (cfd < 0) {
Iterator i;
bool pending = false;
pending = true;
if (!pending) {
r = -ENOENT;
goto fail;
r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, true, &error, NULL);
goto fail;
r = socket_instantiate_service(s);
goto fail;
if (r != -ENOTCONN)
goto fail;
goto fail;
goto fail;
goto fail;
s->n_accepted ++;
goto fail;
s->n_connections ++;
goto fail;
fail:
log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s",
assert(s);
goto fail;
fail:
assert(s);
return -EAGAIN;
return -ENOENT;
return -EBUSY;
s->reset_cpu_usage = true;
assert(s);
return -EAGAIN;
SocketPort *p;
assert(u);
assert(f);
if (s->control_pid > 0)
if (s->control_command_id >= 0)
int copy;
if (p->fd < 0)
if (copy < 0)
return copy;
assert(u);
if (state < 0)
SocketResult f;
else if (f != SOCKET_SUCCESS)
s->result = f;
s->n_accepted += k;
if (id < 0)
SocketPort *p;
SocketPort *p;
SocketPort *p;
SocketPort *p;
if (sscanf(value, "%i %i %n", &fd, &type, &skip) < 2 || fd < 0 || type < 0 || !fdset_contains(fds, fd))
SocketPort *p;
SocketPort *p;
assert(u);
Iterator i;
int fd;
if (p->fd >= 0)
assert(u);
assert(u);
assert(p);
switch (p->type) {
case SOCKET_SOCKET:
case SOCK_STREAM:
case SOCK_DGRAM:
case SOCK_SEQPACKET:
case SOCK_RAW:
return NULL;
case SOCKET_SPECIAL:
case SOCKET_MQUEUE:
case SOCKET_FIFO:
return NULL;
assert(u);
return s->n_connections > 0;
assert(p);
log_unit_error(UNIT(p->socket), "Got POLLHUP on a listening socket. The service probably invoked shutdown() on it, and should better not do that.");
goto fail;
if (cfd < 0) {
goto fail;
fail:
SocketResult f;
assert(s);
s->control_pid = 0;
f = SOCKET_SUCCESS;
if (s->control_command) {
f = SOCKET_SUCCESS;
if (f != SOCKET_SUCCESS)
s->result = f;
if (s->control_command &&
f == SOCKET_SUCCESS) {
socket_run_next(s);
switch (s->state) {
case SOCKET_START_PRE:
if (f == SOCKET_SUCCESS)
case SOCKET_START_CHOWN:
if (f == SOCKET_SUCCESS)
socket_enter_stop_pre(s, f);
case SOCKET_START_POST:
if (f == SOCKET_SUCCESS)
socket_enter_stop_pre(s, f);
case SOCKET_STOP_PRE:
case SOCKET_STOP_PRE_SIGTERM:
case SOCKET_STOP_PRE_SIGKILL:
socket_enter_stop_post(s, f);
case SOCKET_STOP_POST:
case SOCKET_FINAL_SIGTERM:
case SOCKET_FINAL_SIGKILL:
socket_enter_dead(s, f);
assert(s);
switch (s->state) {
case SOCKET_START_PRE:
case SOCKET_START_CHOWN:
case SOCKET_START_POST:
case SOCKET_STOP_PRE:
case SOCKET_STOP_PRE_SIGTERM:
case SOCKET_STOP_PRE_SIGKILL:
case SOCKET_STOP_POST:
case SOCKET_FINAL_SIGTERM:
case SOCKET_FINAL_SIGKILL:
int *rfds;
unsigned rn_fds, k;
SocketPort *p;
assert(s);
rn_fds = 0;
if (p->fd >= 0)
rn_fds++;
if (rn_fds <= 0) {
*n_fds = 0;
if (!rfds)
return -ENOMEM;
if (p->fd >= 0)
assert(s);
assert(s);
log_unit_debug(UNIT(s), "Got notified about service death (failed permanently: %s)", yes_no(failed_permanent));
if (failed_permanent)
assert(s);
s->n_connections--;
assert(u);
s->accept)
socket_notify_service_dead(s, false);
if (!s->timer_event_source)
.sections =
.finished_start_job = {
.finished_stop_job = {