]> git.ipfire.org Git - thirdparty/systemd.git/commit
core: Serialize both pid and pidfd to keep downgrades working
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 3 Apr 2024 14:06:14 +0000 (16:06 +0200)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 5 Apr 2024 03:56:26 +0000 (12:56 +0900)
commitaaa872a71356a2599f028825125005f225384b95
tree7f2f9a1bdbb3d601dd1d923809eca9776e8edf87
parent1ce28e5a248b15e278e8585c154c38c31574ca83
core: Serialize both pid and pidfd to keep downgrades working

Currently, when downgrading from a version with pidfd support to a
version without pidfd support, all information about running processes
is lost as the newer systemd will serialized pidfds which are not recognized
by the older systemd when deserializing.

To improve the situation, let's serialize both the pid and the pidfd.
This is safe because existing versions will either replace the first
deserialized pidref with the second one or discard the second one in
favor of the first one depending on the unit and field. Older versions
that don't support pidfd's will silently discard any fields that contain
a pidfd as those will try to parse the field as a pid and since a pidfd
field will start with '@', those versions will debug error log and ignore
the value.

To make sure we reuse the existing pidfd as much as possible, the pidfd
is serialized first. Both for scopes and service main pids, if the same
pid is seen multiple times, the first pidref is kept. So by serializing
the pidfd first we make sure the original pidfd is used instead of the
new one which is opened when deserializing the first pid field.

For other control units, older versions with pidfd support will discard
the first pidfd and replace it with a new pidfd from the second pid field.
This is a slight regression on downgrades, but we make sure it doesn't
happen for future versions (and older versions when this commit is
backported) by modifying the logic to only use the first successfully
deserialized pidref so that the raw pid without pidfd is discarded instead
of it replacing the existing pidfd.
src/core/mount.c
src/core/service.c
src/core/socket.c
src/core/swap.c
src/shared/serialize.c