Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos/switch-to-configuration: Document and test handling of socket-activated services #161838

Merged
merged 2 commits into from
Mar 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions nixos/doc/manual/development/unit-handling.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,18 @@ checks:
`RefuseManualStop` in the `[Unit]` section, and `X-OnlyManualStart` in the
`[Unit]` section.

- The rest of the behavior is decided whether the unit has `X-StopIfChanged`
in the `[Service]` section set (exposed via
- Further behavior depends on the unit having `X-StopIfChanged` in the
`[Service]` section set to `true` (exposed via
[systemd.services.\<name\>.stopIfChanged](#opt-systemd.services)). This is
set to `true` by default and must be explicitly turned off if not wanted.
If the flag is enabled, the unit is **stop**ped and then **start**ed. If
dasJ marked this conversation as resolved.
Show resolved Hide resolved
not, the unit is **restart**ed. The goal of the flag is to make sure that
the new unit never runs in the old environment which is still in place
before the activation script is run.
before the activation script is run. This behavior is different when the
service is socket-activated, as outlined in the following steps.

- The last thing that is taken into account is whether the unit is a service
and socket-activated. Due to a bug, this is currently only done when
`X-StopIfChanged` is set. If the unit is socket-activated, the socket is
stopped and started, and the service is stopped and to be started by socket
activation.
and socket-activated. If `X-StopIfChanged` is **not** set, the service
is **restart**ed with the others. If it is set, both the service and the
socket are **stop**ped and the socket is **start**ed, leaving socket
activation to start the service when it's needed.
22 changes: 14 additions & 8 deletions nixos/doc/manual/from_md/development/unit-handling.section.xml
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@
</listitem>
<listitem>
<para>
The rest of the behavior is decided whether the unit has
Further behavior depends on the unit having
<literal>X-StopIfChanged</literal> in the
<literal>[Service]</literal> section set (exposed via
<literal>[Service]</literal> section set to
<literal>true</literal> (exposed via
<link linkend="opt-systemd.services">systemd.services.&lt;name&gt;.stopIfChanged</link>).
This is set to <literal>true</literal> by default and must
be explicitly turned off if not wanted. If the flag is
Expand All @@ -100,17 +101,22 @@
is <emphasis role="strong">restart</emphasis>ed. The goal of
the flag is to make sure that the new unit never runs in the
old environment which is still in place before the
activation script is run.
activation script is run. This behavior is different when
the service is socket-activated, as outlined in the
following steps.
</para>
</listitem>
<listitem>
<para>
The last thing that is taken into account is whether the
unit is a service and socket-activated. Due to a bug, this
is currently only done when
<literal>X-StopIfChanged</literal> is set. If the unit is
socket-activated, the socket is stopped and started, and the
service is stopped and to be started by socket activation.
unit is a service and socket-activated. If
<literal>X-StopIfChanged</literal> is
<emphasis role="strong">not</emphasis> set, the service is
<emphasis role="strong">restart</emphasis>ed with the
others. If it is set, both the service and the socket are
<emphasis role="strong">stop</emphasis>ped and the socket is
<emphasis role="strong">start</emphasis>ed, leaving socket
activation to start the service when it’s needed.
</para>
</listitem>
</itemizedlist>
Expand Down
9 changes: 6 additions & 3 deletions nixos/modules/system/activation/switch-to-configuration.pl
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ sub handleModifiedUnit {
# seem to get applied on daemon-reload.
} elsif ($unit =~ /\.mount$/) {
# Reload the changed mount unit to force a remount.
# FIXME: only reload when Options= changed, restart otherwise
$unitsToReload->{$unit} = 1;
recordUnit($reloadListFile, $unit);
} elsif ($unit =~ /\.socket$/) {
Expand Down Expand Up @@ -339,21 +340,23 @@ sub handleModifiedUnit {
# If this unit is socket-activated, then stop the
# socket unit(s) as well, and restart the
# socket(s) instead of the service.
my $socketActivated = 0;
my $socket_activated = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this snake case when all the other variables are camel case?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense, but what is unitsToReload?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is currently a mix between camel case (not yet refactored) and snake case (already refactored)

if ($unit =~ /\.service$/) {
my @sockets = split(/ /, join(" ", @{$unitInfo{Service}{Sockets} // []}));
if (scalar @sockets == 0) {
@sockets = ("$baseName.socket");
}
foreach my $socket (@sockets) {
if (defined $activePrev->{$socket}) {
# We can now be sure this is a socket-activate unit

$unitsToStop->{$socket} = 1;
# Only restart sockets that actually
# exist in new configuration:
if (-e "$out/etc/systemd/system/$socket") {
$unitsToStart->{$socket} = 1;
recordUnit($startListFile, $socket);
$socketActivated = 1;
$socket_activated = 1;
}
# Remove from units to reload so we don't restart and reload
if ($unitsToReload->{$unit}) {
Expand All @@ -368,7 +371,7 @@ sub handleModifiedUnit {
# that this unit needs to be started below.
# We write this to a file to ensure that the
# service gets restarted if we're interrupted.
if (!$socketActivated) {
if (!$socket_activated) {
$unitsToStart->{$unit} = 1;
recordUnit($startListFile, $unit);
}
Expand Down
Loading