socket: New option 'FlushPending' (boolean) to flush socket before entering listening state

Disabled by default. When Enabled, before listening on the socket, flush the content.
Applies when Accept=no only.
This commit is contained in:
Renaud Métrich 2020-08-20 13:00:37 +02:00 committed by Lennart Poettering
parent f77d6ec953
commit 3e5f04bf64
8 changed files with 39 additions and 0 deletions

View File

@ -415,6 +415,7 @@ Most socket unit settings are available to transient units.
✓ SocketMode=
✓ DirectoryMode=
✓ Accept=
✓ FlushPending=
✓ Writable=
✓ MaxConnections=
✓ MaxConnectionsPerSource=

View File

@ -3950,6 +3950,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u NRefused = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u FlushPending = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s FileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SocketProtocol = ...;
@ -5031,6 +5033,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="NRefused"/>
<variablelist class="dbus-property" generated="True" extra-ref="FlushPending"/>
<variablelist class="dbus-property" generated="True" extra-ref="FileDescriptorName"/>
<variablelist class="dbus-property" generated="True" extra-ref="SocketProtocol"/>
@ -5508,6 +5512,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
meaning as they have for the corresponding field of service units (see above). In addition to that,
the value <literal>service-failed-permanent</literal> indicates that the service of this socket failed
continuously.</para>
<para><varname>FlushPending</varname> specifies whether to flush the socket
just before entering the listening state. This setting only applies to sockets with
<varname>Accept=</varname> set to <literal>no</literal>.</para>
</refsect2>
</refsect1>

View File

@ -427,6 +427,18 @@
false, in read-only mode. Defaults to false.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>FlushPending=</varname></term>
<listitem><para>Takes a boolean argument. May only be used when
<option>Accept=no</option>. If yes, the socket's buffers are cleared after the
triggered service exited. This causes any pending data to be
flushed and any pending incoming connections to be rejected. If no, the
socket's buffers won't be cleared, permitting the service to handle any
pending connections after restart, which is the usually expected behaviour.
Defaults to <option>no</option>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>MaxConnections=</varname></term>
<listitem><para>The maximum number of connections to

View File

@ -86,6 +86,7 @@ const sd_bus_vtable bus_socket_vtable[] = {
SD_BUS_PROPERTY("SocketMode", "u", bus_property_get_mode, offsetof(Socket, socket_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Socket, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Accept", "b", bus_property_get_bool, offsetof(Socket, accept), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("FlushPending", "b", bus_property_get_bool, offsetof(Socket, flush_pending), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Writable", "b", bus_property_get_bool, offsetof(Socket, writable), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KeepAlive", "b", bus_property_get_bool, offsetof(Socket, keep_alive), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KeepAliveTimeUSec", "t", bus_property_get_usec, offsetof(Socket, keep_alive_time), SD_BUS_VTABLE_PROPERTY_CONST),
@ -179,6 +180,9 @@ static int bus_socket_set_transient_property(
if (streq(name, "Accept"))
return bus_set_transient_bool(u, name, &s->accept, message, flags, error);
if (streq(name, "FlushPending"))
return bus_set_transient_bool(u, name, &s->flush_pending, message, flags, error);
if (streq(name, "Writable"))
return bus_set_transient_bool(u, name, &s->writable, message, flags, error);

View File

@ -391,6 +391,7 @@ Socket.SocketGroup, config_parse_user_group_compat, 0,
Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode)
Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode)
Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept)
Socket.FlushPending, config_parse_bool, 0, offsetof(Socket, flush_pending)
Socket.Writable, config_parse_bool, 0, offsetof(Socket, writable)
Socket.MaxConnections, config_parse_unsigned, 0, offsetof(Socket, max_connections)
Socket.MaxConnectionsPerSource, config_parse_unsigned, 0, offsetof(Socket, max_connections_per_source)

View File

@ -72,6 +72,7 @@ static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
static void flush_ports(Socket *s);
static void socket_init(Unit *u) {
Socket *s = SOCKET(u);
@ -669,6 +670,11 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
prefix, s->n_connections,
prefix, s->max_connections,
prefix, s->max_connections_per_source);
else
fprintf(f,
"%sFlushPending: %s\n",
prefix, yes_no(s->flush_pending));
if (s->priority >= 0)
fprintf(f,
@ -2201,6 +2207,11 @@ static void socket_enter_listening(Socket *s) {
int r;
assert(s);
if (!s->accept && s->flush_pending) {
log_unit_debug(UNIT(s), "Flushing socket before listening.");
flush_ports(s);
}
r = socket_watch_fds(s);
if (r < 0) {
log_unit_warning_errno(UNIT(s), r, "Failed to watch sockets: %m");

View File

@ -110,6 +110,7 @@ struct Socket {
bool accept;
bool remove_on_stop;
bool writable;
bool flush_pending;
int socket_protocol;

View File

@ -1956,6 +1956,7 @@ static int bus_append_socket_property(sd_bus_message *m, const char *field, cons
int r;
if (STR_IN_SET(field, "Accept",
"FlushPending",
"Writable",
"KeepAlive",
"NoDelay",