Comment 18 for bug 1642966

Revision history for this message
Robie Basak (racb) wrote :

I think this might be caused by an interesting interaction between systemd, debhelper and the CUPS scheduler.

I can reproduce a very similar error with the following. I think (though am not sure) that this is related to the root cause. On a fresh Xenial system:

sudo apt-get update && sudo apt-get -y install cups
sudo -i
systemctl stop cups.service
sleep 4
touch /var/cache/cups/org.cups.cupsd
sleep 4
sudo rm /var/cache/cups/org.cups.cupsd
sleep 4
systemctl stop cups.service

(the sleeps are to avoid any unknown, additional and unintentional race conditions)

This results in an exit status of 1 and the message "Job for cups.service canceled." which matches the error that reporters have been seeing.

In other words, if cups.service is started via cups.path, that cause is removed, and then we request a manual stop of cups.service, then systemd refuses to stop the service the first time (a retry always succeeds for me).

In cups-daemon.prerm, debhelper has added "deb-systemd-invoke stop cups.path" followed by "invoke-rc.d cups stop || exit $?". I believe the second invocation is ultimately equivalent to "systemctl stop cups.service" and fails the same way as in my example, causing the prerm to exit 1, causing the dpkg failure reported.

I'm not sure of the intended logic for /lib/systemd/system/cups.path here. AFAICT, it exists because when using CUPS with launchd, the CUPS daemon leaves the file in place as long as it doesn't want to be terminated, and removes it when it wants to be terminated before it exits anyway. Is this because launchd kills daemons itself unless the keepalive file exists?

With systemd, I can't find any documentation that suggests that systemd ever intends to automatically kill a socket activated daemon. AFAICT, it's entirely up to the daemon when it chooses to exit. So there appears to be no need for cupsd to maintain /var/cache/cups/org.cups.cupsd when running under systemd.

As configured right now, systemd will also start cupsd if /var/cache/cups/org.cups.cupsd is created while cupsd is not running. I can't find anything that might use this function. So either this is an accidental side-effect that is not needed, or I have missed some other path that does need this.

systemd talks about CUPS in a blog post that is relevant: http://0pointer.de/blog/projects/socket-activation2.html. Note that this only sets up a path unit for /var/spool/cups, not any kind of keepalive file for cupsd.