#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <mqueue.h>
-#ifdef HAVE_XATTR
-#include <attr/xattr.h>
-#endif
+#include <sys/xattr.h>
#include "sd-event.h"
#include "log.h"
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);
-
- unit_cgroup_context_init_defaults(u, &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, &s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_usec, 0, socket_dispatch_timer, s);
+ 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) {
if (r < 0)
return r;
- r = unit_exec_context_patch_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;
}
"%sBroadcast: %s\n"
"%sPassCredentials: %s\n"
"%sPassSecurity: %s\n"
- "%sTCPCongestion: %s\n",
+ "%sTCPCongestion: %s\n"
+ "%sRemoveOnStop: %s\n",
prefix, socket_state_to_string(s->state),
prefix, socket_result_to_string(s->result),
prefix, socket_address_bind_ipv6_only_to_string(s->bind_ipv6_only),
prefix, yes_no(s->broadcast),
prefix, yes_no(s->pass_cred),
prefix, yes_no(s->pass_sec),
- prefix, strna(s->tcp_congestion));
+ prefix, strna(s->tcp_congestion),
+ prefix, yes_no(s->remove_on_stop));
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,
int k;
k = getpeercred(fd, &ucred);
- if (k < 0)
+ 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;
- if (asprintf(&r,
- "%u-%lu-%lu",
- nr,
- (unsigned long) ucred.pid,
- (unsigned long) ucred.uid) < 0)
- return -ENOMEM;
-
break;
}
if (p->fd < 0)
continue;
- close_nointr_nofail(p->fd);
+ p->fd = safe_close(p->fd);
+
+ /* One little note: we should normally not delete any
+ * sockets in the file system here! After all some
+ * other process we spawned might still have a
+ * reference of this fd and wants to continue to use
+ * it. Therefore we delete sockets in the file system
+ * before we create a new one, not after we stopped
+ * using one! */
+
+ if (s->remove_on_stop) {
+ switch (p->type) {
- /* One little note: we should never delete any sockets
- * in the file system here! After all some other
- * process we spawned might still have a reference of
- * this fd and wants to continue to use it. Therefore
- * we delete sockets in the file system before we
- * create a new one, not after we stopped using
- * one! */
+ case SOCKET_FIFO:
+ unlink(p->path);
+ break;
+
+ case SOCKET_MQUEUE:
+ mq_unlink(p->path);
+ break;
+
+ case SOCKET_SOCKET:
+ socket_address_unlink(&p->address);
+ break;
- p->fd = -1;
+ default:
+ break;
+ }
+ }
}
}
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 (!know_label) {
- if ((r = socket_instantiate_service(s)) < 0)
+ r = socket_instantiate_service(s);
+ if (r < 0)
return r;
if (UNIT_ISSET(s->service) &&
SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START]) {
r = label_get_create_label_from_exe(SERVICE(UNIT_DEREF(s->service))->exec_command[SERVICE_EXEC_START]->path, &label);
-
- if (r < 0) {
- if (r != -EPERM)
- return r;
- }
+ if (r < 0 && r != -EPERM)
+ return r;
}
know_label = true;
old_state = s->state;
s->state = state;
- if (state != SOCKET_START_PRE &&
- state != SOCKET_START_POST &&
- state != SOCKET_STOP_PRE &&
- state != SOCKET_STOP_PRE_SIGTERM &&
- state != SOCKET_STOP_PRE_SIGKILL &&
- state != SOCKET_STOP_POST &&
- state != SOCKET_FINAL_SIGTERM &&
- state != SOCKET_FINAL_SIGKILL) {
+ if (!IN_SET(state,
+ SOCKET_START_PRE,
+ SOCKET_START_POST,
+ SOCKET_STOP_PRE,
+ SOCKET_STOP_PRE_SIGTERM,
+ SOCKET_STOP_PRE_SIGKILL,
+ SOCKET_STOP_POST,
+ SOCKET_FINAL_SIGTERM,
+ SOCKET_FINAL_SIGKILL)) {
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
socket_unwatch_control_pid(s);
if (state != SOCKET_LISTENING)
socket_unwatch_fds(s);
- if (state != SOCKET_START_POST &&
- state != SOCKET_LISTENING &&
- state != SOCKET_RUNNING &&
- state != SOCKET_STOP_PRE &&
- state != SOCKET_STOP_PRE_SIGTERM &&
- state != SOCKET_STOP_PRE_SIGKILL)
+ if (!IN_SET(state,
+ SOCKET_START_POST,
+ SOCKET_LISTENING,
+ SOCKET_RUNNING,
+ SOCKET_STOP_PRE,
+ SOCKET_STOP_PRE_SIGTERM,
+ SOCKET_STOP_PRE_SIGKILL))
socket_close_fds(s);
if (state != old_state)
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 (!pending) {
+ if (!UNIT_ISSET(s->service)) {
+ log_error_unit(UNIT(s)->id, "%s: service to activate vanished, refusing activation.", UNIT(s)->id);
+ r = -ENOENT;
+ goto fail;
+ }
+
r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, true, &error, NULL);
if (r < 0)
goto fail;
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);
}
}