mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-26 10:03:40 +03:00
socket: optionally remove sockets/FIFOs in the file system after use
This commit is contained in:
parent
edf029b7fd
commit
bd1fe7c79d
@ -730,6 +730,25 @@
|
||||
option.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>RemoveOnStop=</varname></term>
|
||||
<listitem><para>Takes a boolean
|
||||
argument. If enabled any file nodes
|
||||
created by this socket unit are
|
||||
removed when it is stopped. This
|
||||
applies to AF_UNIX sockets in the file
|
||||
system, POSIX message queues as well
|
||||
as FIFOs. Normally it should not be
|
||||
necessary to use this option, and is
|
||||
not recommended as services might
|
||||
continue to run after the socket unit
|
||||
has been terminated and it should
|
||||
still be possible to communicate with
|
||||
them via their file system
|
||||
node. Defaults to
|
||||
off.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
<para>Check
|
||||
|
@ -106,6 +106,7 @@ const sd_bus_vtable bus_socket_vtable[] = {
|
||||
SD_BUS_PROPERTY("Broadcast", "b", bus_property_get_bool, offsetof(Socket, broadcast), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("PassCredentials", "b", bus_property_get_bool, offsetof(Socket, pass_cred), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("PassSecurity", "b", bus_property_get_bool, offsetof(Socket, pass_sec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RemoveOnStop", "b", bus_property_get_bool, offsetof(Socket, remove_on_stop), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Listen", "a(ss)", property_get_listen, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Mark", "i", bus_property_get_int, offsetof(Socket, mark), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("MaxConnections", "u", bus_property_get_unsigned, offsetof(Socket, max_connections), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
@ -242,6 +242,7 @@ Socket.TCPCongestion, config_parse_string, 0,
|
||||
Socket.ReusePort, config_parse_bool, 0, offsetof(Socket, reuse_port)
|
||||
Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg)
|
||||
Socket.MessageQueueMessageSize, config_parse_long, 0, offsetof(Socket, mq_msgsize)
|
||||
Socket.RemoveOnStop, config_parse_bool, 0, offsetof(Socket, remove_on_stop)
|
||||
Socket.Service, config_parse_socket_service, 0, 0
|
||||
m4_ifdef(`HAVE_SMACK',
|
||||
`Socket.SmackLabel, config_parse_string, 0, offsetof(Socket, smack)
|
||||
|
@ -451,7 +451,8 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
"%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),
|
||||
@ -464,7 +465,8 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
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,
|
||||
@ -702,13 +704,33 @@ static void socket_close_fds(Socket *s) {
|
||||
|
||||
p->fd = safe_close(p->fd);
|
||||
|
||||
/* 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! */
|
||||
/* 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) {
|
||||
|
||||
case SOCKET_FIFO:
|
||||
unlink(p->path);
|
||||
break;
|
||||
|
||||
case SOCKET_MQUEUE:
|
||||
mq_unlink(p->path);
|
||||
break;
|
||||
|
||||
case SOCKET_SOCKET:
|
||||
socket_address_unlink(&p->address);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -993,17 +1015,15 @@ static int socket_open_fds(Socket *s) {
|
||||
|
||||
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;
|
||||
@ -1121,14 +1141,15 @@ static void socket_set_state(Socket *s, SocketState state) {
|
||||
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);
|
||||
@ -1139,12 +1160,13 @@ static void socket_set_state(Socket *s, SocketState state) {
|
||||
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)
|
||||
|
@ -126,6 +126,7 @@ struct Socket {
|
||||
SocketResult result;
|
||||
|
||||
bool accept;
|
||||
bool remove_on_stop;
|
||||
|
||||
/* Socket options */
|
||||
bool keep_alive;
|
||||
|
@ -625,6 +625,21 @@ int getsockname_pretty(int fd, char **ret) {
|
||||
return sockaddr_pretty(&sa.sa, salen, false, ret);
|
||||
}
|
||||
|
||||
int socket_address_unlink(SocketAddress *a) {
|
||||
assert(a);
|
||||
|
||||
if (socket_address_family(a) != AF_UNIX)
|
||||
return 0;
|
||||
|
||||
if (a->sockaddr.un.sun_path[0] == 0)
|
||||
return 0;
|
||||
|
||||
if (unlink(a->sockaddr.un.sun_path) < 0)
|
||||
return -errno;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char* const netlink_family_table[] = {
|
||||
[NETLINK_ROUTE] = "route",
|
||||
[NETLINK_FIREWALL] = "firewall",
|
||||
|
@ -70,6 +70,7 @@ int socket_address_parse(SocketAddress *a, const char *s);
|
||||
int socket_address_parse_netlink(SocketAddress *a, const char *s);
|
||||
int socket_address_print(const SocketAddress *a, char **p);
|
||||
int socket_address_verify(const SocketAddress *a) _pure_;
|
||||
int socket_address_unlink(SocketAddress *a);
|
||||
|
||||
bool socket_address_can_accept(const SocketAddress *a) _pure_;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user