• Bug#1091519: deb-systemd-helper: Fails when non-existing unit is listed

    From Andrea Bolognani@21:1/5 to All on Fri Dec 27 23:20:01 2024
    --pup2xyi3grf3sx6e
    Content-Type: text/plain; charset=utf-8
    Content-Disposition: inline
    Content-Transfer-Encoding: quoted-printable

    Package: init-system-helpers
    Version: 1.67
    Severity: normal
    Tags: patch

    When installing libvirt-daemon on a testing/unstable system, the
    following error message is reported:

    /usr/bin/deb-systemd-helper: error: unable to read virtlockd.socket

    Full debug output, with useless information redacted:

    $ sudo _DEB_SYSTEMD_HELPER_DEBUG=1 apt-get install --no-install-recommends libvirt-daemon
    The following NEW packages will be installed:
    libvirt-daemon
    Selecting previously unselected package libvirt-daemon.
    Unpacking libvirt-daemon (10.10.0-3) ...
    Setting up libvirt-daemon (10.10.0-3) ...
    (deb-systemd-helper DEBUG) is purge = no
    (deb-systemd-helper DEBUG) action = unmask, scriptname = libvirtd.service, service_path = /lib/systemd/system/libvirtd.service
    (deb-systemd-helper DEBUG) rmdir_if_empty /var/lib/systemd/deb-systemd-helper-masked
    (deb-systemd-helper DEBUG) rmdir(/var/lib/systemd/deb-systemd-helper-masked) failed (No such file or directory)
    (deb-systemd-helper DEBUG) rmdir_if_empty /var/lib/systemd/deb-systemd-user-helper-masked
    (deb-systemd-helper DEBUG) rmdir(/var/lib/systemd/deb-systemd-user-helper-masked) failed (No such file or directory)
    (deb-systemd-helper DEBUG) is purge = no
    (deb-systemd-helper DEBUG) action = was-enabled, scriptname = libvirtd.service, service_path = /lib/systemd/system/libvirtd.service
    (deb-systemd-helper DEBUG) Reading state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd.service.dsh-also
    (deb-systemd-helper DEBUG) Contents: $VAR1 = [];

    (deb-systemd-helper DEBUG) All links present, considering libvirtd.service was-enabled.
    (deb-systemd-helper DEBUG) is purge = no
    (deb-systemd-helper DEBUG) action = enable, scriptname = libvirtd.service, service_path = /lib/systemd/system/libvirtd.service
    (deb-systemd-helper DEBUG) Using systemctl preset to enable libvirtd.service
    Failed to enable auxiliary unit virtlockd.socket, ignoring.
    Created symlink '/etc/systemd/system/sockets.target.wants/libvirtd.socket' → '/usr/lib/systemd/system/libvirtd.socket'.
    Created symlink '/etc/systemd/system/sockets.target.wants/libvirtd-ro.socket' → '/usr/lib/systemd/system/libvirtd-ro.socket'.
    Created symlink '/etc/systemd/system/sockets.target.wants/libvirtd-admin.socket' → '/usr/lib/systemd/system/libvirtd-admin.socket'.
    /usr/bin/deb-systemd-helper: error: unable to read virtlockd.socket
    (deb-systemd-helper DEBUG) is purge = no
    (deb-systemd-helper DEBUG) action = unmask, scriptname = libvirtd-admin.socket, service_path = /lib/systemd/system/libvirtd-admin.socket
    (deb-systemd-helper DEBUG) rmdir_if_empty /var/lib/systemd/deb-systemd-helper-masked
    (deb-systemd-helper DEBUG) rmdir(/var/lib/systemd/deb-systemd-helper-masked) failed (No such file or directory)
    (deb-systemd-helper DEBUG) rmdir_if_empty /var/lib/systemd/deb-systemd-user-helper-masked
    (deb-systemd-helper DEBUG) rmdir(/var/lib/systemd/deb-systemd-user-helper-masked) failed (No such file or directory)
    (deb-systemd-helper DEBUG) is purge = no
    (deb-systemd-helper DEBUG) action = was-enabled, scriptname = libvirtd-admin.socket, service_path = /lib/systemd/system/libvirtd-admin.socket
    (deb-systemd-helper DEBUG) Reading state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-admin.socket.dsh-also
    (deb-systemd-helper DEBUG) Contents: $VAR1 = [];

    (deb-systemd-helper DEBUG) All links present, considering libvirtd-admin.socket was-enabled.
    (deb-systemd-helper DEBUG) is purge = no
    (deb-systemd-helper DEBUG) action = enable, scriptname = libvirtd-admin.socket, service_path = /lib/systemd/system/libvirtd-admin.socket
    (deb-systemd-helper DEBUG) Using systemctl preset to enable libvirtd-admin.socket
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.statefOsJc.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-admin.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.statenPIoH.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-admin.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.stateLCkXc.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-admin.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.statep2PDL.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-admin.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.stateM29Ok.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-admin.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.stateF7a2H.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-admin.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.stateDAd0c.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-admin.socket.dsh-also
    (deb-systemd-helper DEBUG) is purge = no
    (deb-systemd-helper DEBUG) action = unmask, scriptname = libvirtd-ro.socket, service_path = /lib/systemd/system/libvirtd-ro.socket
    (deb-systemd-helper DEBUG) rmdir_if_empty /var/lib/systemd/deb-systemd-helper-masked
    (deb-systemd-helper DEBUG) rmdir(/var/lib/systemd/deb-systemd-helper-masked) failed (No such file or directory)
    (deb-systemd-helper DEBUG) rmdir_if_empty /var/lib/systemd/deb-systemd-user-helper-masked
    (deb-systemd-helper DEBUG) rmdir(/var/lib/systemd/deb-systemd-user-helper-masked) failed (No such file or directory)
    (deb-systemd-helper DEBUG) is purge = no
    (deb-systemd-helper DEBUG) action = was-enabled, scriptname = libvirtd-ro.socket, service_path = /lib/systemd/system/libvirtd-ro.socket
    (deb-systemd-helper DEBUG) Reading state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-ro.socket.dsh-also
    (deb-systemd-helper DEBUG) Contents: $VAR1 = [];

    (deb-systemd-helper DEBUG) All links present, considering libvirtd-ro.socket was-enabled.
    (deb-systemd-helper DEBUG) is purge = no
    (deb-systemd-helper DEBUG) action = enable, scriptname = libvirtd-ro.socket, service_path = /lib/systemd/system/libvirtd-ro.socket
    (deb-systemd-helper DEBUG) Using systemctl preset to enable libvirtd-ro.socket
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.statetIBlZ.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-ro.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.stateBihfm.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-ro.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.stateH5caR.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-ro.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.stateQDBhi.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-ro.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.state1lH4W.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-ro.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.stateXiC5q.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-ro.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.statepS8xr.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd-ro.socket.dsh-also
    (deb-systemd-helper DEBUG) is purge = no
    (deb-systemd-helper DEBUG) action = unmask, scriptname = libvirtd.socket, service_path = /lib/systemd/system/libvirtd.socket
    (deb-systemd-helper DEBUG) rmdir_if_empty /var/lib/systemd/deb-systemd-helper-masked
    (deb-systemd-helper DEBUG) rmdir(/var/lib/systemd/deb-systemd-helper-masked) failed (No such file or directory)
    (deb-systemd-helper DEBUG) rmdir_if_empty /var/lib/systemd/deb-systemd-user-helper-masked
    (deb-systemd-helper DEBUG) rmdir(/var/lib/systemd/deb-systemd-user-helper-masked) failed (No such file or directory)
    (deb-systemd-helper DEBUG) is purge = no
    (deb-systemd-helper DEBUG) action = was-enabled, scriptname = libvirtd.socket, service_path = /lib/systemd/system/libvirtd.socket
    (deb-systemd-helper DEBUG) Reading state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd.socket.dsh-also
    (deb-systemd-helper DEBUG) Contents: $VAR1 = [];

    (deb-systemd-helper DEBUG) All links present, considering libvirtd.socket was-enabled.
    (deb-systemd-helper DEBUG) is purge = no
    (deb-systemd-helper DEBUG) action = enable, scriptname = libvirtd.socket, service_path = /lib/systemd/system/libvirtd.socket
    (deb-systemd-helper DEBUG) Using systemctl preset to enable libvirtd.socket
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.state0LqFQ.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.statePtygq.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.stateyivti.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.statelrMK_.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.statesTPSG.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.state2YGDX.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd.socket.dsh-also
    (deb-systemd-helper DEBUG) Renaming temp file /var/lib/systemd/deb-systemd-helper-enabled/.stateQmQOZ.tmp to state file /var/lib/systemd/deb-systemd-helper-enabled/libvirtd.socket.dsh-also

    Note that I had installed all dependencies (libvirt-daemon-common, libvirt-daemon-log) ahead of time to ensure that only the relevant
    package would be included in this transaction.

    This issue has been reported several months ago as

    https://bugs.debian.org/1082939

    and unfortunately I hadn't been able to turn that into a proper
    report against init-system-helpers until now. Apologies for the
    delay.

    The root cause is that libvirtd.service contains

    [Install]
    Also=virtlockd.socket

    but virtlockd (as well as its sockets) is shipped in the
    libvirt-daemon-lock package, and the libvirt-daemon package (which
    contains libvirtd and its sockets) *intentionally* does not Depend on
    it.

    The explanation is that virtlockd is a soft dependency for libvirtd: specifically, libvirtd.service contains

    [Unit]
    Wants=virtlockd.socket
    After=virtlockd.socket

    but it can work perfectly well without it, and in fact in most cases
    the virtlockd integration will be disabled, as per default
    configuration. This is why Wants= is used instead of Requires=.

    systemd itself handles this nicely by simply ignoring the soft
    dependency when the corresponing unit doesn't exist.
    deb-systemd-helper, on the other hand, reports an error and refuses
    to create the libvirtd.service.dsh-also state file, which in turns
    results in partial cleanup on purge as well as potentially other
    side-effects that I haven't noticed.

    I believe that deb-systemd-helper should follow systemd's example and
    treat this situation more gracefully, but to be completely honest I
    don't fully understand what its state files are used for in the first
    place, so it's quite possible that this take is unhelpfully naive :)

    I've attached a tentative patch that turns the hard failure into a
    soft one. Consider it a mere conversation starter.

    Cheers.

    --
    Andrea Bolognani <eof@kiyuko.org>
    Resistance is futile, you will be garbage collected.

    --pup2xyi3grf3sx6e
    Content-Type: text/x-diff; charset=us-ascii
    Content-Disposition: attachment; filename="deb-systemd-helper.diff"

    diff -Naru a/script/deb-systemd-helper b/script/deb-systemd-helper
    --- a/script/deb-systemd-helper 2024-12-27 22:59:19.475279724 +0100
    +++ b/script/deb-systemd-helper 2024-12-27 23:00:28.003801265 +0100
    @@ -233,7 +233,10 @@
    # as values. Since unit names can't have whitespace in systemd,
    # simply use split and strip any leading/trailing quotes. See
    # systemd-escape(1) for examples of valid unit names.
    - open my $fh, '<', "$dpkg_root$service_path" or error("unable to read $dpkg_root$service_path");
    + open my $fh, '<', "$dpkg_root$service_path" or do {
    + debug("unable to read $dpkg_root$service_path");
    + return @links;
    + };
    while (my $line = <$fh>) {
    chomp($line);
    my $service_link;

    --pup2xyi3grf3sx6e--

    --