Closed tsipinakis closed 7 years ago
A short-term solution may be to: comment out the SystemdService
line in the service file, perhaps with a relevant comment above it, and also add a note to the build process (make install
target, or install-service
target) about the optional (non-install
ed) dunst.systemd.service
file (with a note that it needs to be renamed to match the assumption in the D-Bus service file).
Note, I simply installed this file to my PREFIX
(~/.local/share/systemd/user/dunst.service
) and there were not complications in having two D-Bus
service files with the same name (file name and internal service name). I have also left the change to DefaultEnvironment
in my ~/.config/systemd/user.conf
(DefaultEnvironment="PATH=/home/nmshculte/.local/bin:$PATH"
), but I don't believe this is necessary in this case.
Setting PATH
shouldn't be necessary since systemd requires full paths to the executable in the Exec*
lines.
While it's a bit heavy handed (read: the configuration affects all of systemd's user units, not just D-Bus/Dunst's environment), it's an important detail for those that run scripts with Dunst (Dunst supports running scripts keyed by notification attribute matching) and expect their PATH
from e.g. ~/.profile
(this is called... an login (or interactive?) session? I'm not sure the proper terminology.).
One could deal with PATH
issues in each script too, but there's no saying that the Dunst configuration (an thus the scripts that care about PATH
) can't be used for multiple Dunst instances (though... maybe this can't happen; I thought I saw a use-case for this in my testing, but I may have just misunderstood).
Ah. I find it better to instead have a target like environment.target
where I have foo-env.service
files which handle the systemctl --user set-environment
calls when starting the service and unset-environment
when stopping it. These services are Before=
and BindsTo=
environment.target
. There's also an x11-environment.target
for X11-specific settings. Then my dunst.service
is Requires=
and After=
x11-environment.target
to ensure it has the right environment.
It's a bit complicated, but it works and keeps things aware of even things like my ssh-agent
from the bottom up instead of trying to set up SSH_AGENT_SOCK
in every .service
file which might care about it.
(My entire setup is managed by systemd
including starting X, the window manager, etc., so I don't have a .profile
or (meaningful) .xinitrc
.)
This only happens if [dbus-daemon] is started with the
--systemd-activation
flag and it looks like in that case if the service file is not found it ignores theExec
line.
(I am an upstream D-Bus maintainer.)
Yes, that's how it works. On systems where dbus-daemon --session
is started with --systemd-activation
, each D-Bus session service is either a traditional D-Bus service (always run via Exec
as though --systemd-activation
had not been used, with no SystemdService
) or a hybrid D-Bus/systemd service (always run by starting the SystemdService
, never Exec
).
You have to either install everything necessary to run dunst as a systemd user service (the unit file and the SystemdService
line), or none of it. Providing the SystemdService
line but not the unit file that it references is not correct, in the same way that it would not be valid to install a D-Bus service to /usr/local/share/dbus-1/services
with Exec=/usr/local/bin/dunst-wrapper-script
without also installing dunst-wrapper-script
.
A short-term solution may be to: comment out the
SystemdService
line in the service file, perhaps with a relevant comment above it, and also add a note to the build process (make install
target, orinstall-service
target) about the optional (non-installed)dunst.systemd.service
file (with a note that it needs to be renamed to match the assumption in the D-Bus service file).
This would be better than the current situation.
Better still, IMO, would be to install the systemd service. On non-systemd systems, and on systemd systems where the OS integrator has not chosen to start dbus-daemon --session --systemd-activation
from systemd, it is useless but harmless (one extra installed file that nothing will read). On systems where dbus-daemon's systemd activation feature has been enabled, it results in dunst getting placed in its own cgroup for management and resource control, rather than being treated like part of dbus-daemon.
(If a distro like Debian or Fedora sets up your dbus-daemon and systemd, they are your OS integrator. If you do it yourself, you are the OS integrator. Either way, it needs to be done by someone who knows what they're doing.)
While it's a bit heavy handed (read: the configuration affects all of systemd's user units, not just D-Bus/Dunst's environment), [manipulating the activation environment is] an important detail for those that run scripts with Dunst
Yes, getting the right environment for systemd-activated things is important, but this is not Dunst's job. Arranging for the right environment variables to be pushed into systemd --user
and dbus-daemon --session
, including uploading them from ~/.profile
if that is felt to be necessary, is a job for the OS integrator: it is something that needs to be done for all user-services.
I honestly don't see that there's much more that can be done on the dunst side here. The provided dunst.service file work okay on a properly configured system (though only for X11!).
The only thing that needs to be done here is remove the Environment=DISPLAY=:0
line, since:
systemctl --user set-environment
elsewhere.Other than that, the code provided by dunst will only fail if the OS Integrator has provided something inconsistent, and nothing can be done about that here/downstream.
I honestly don't see that there's much more that can be done on the dunst side here
Please do as the first comment said: either remove the SystemdService
line from the D-Bus service file, or install the systemd unit at the same time you install the D-Bus service file.
(Or if you insist on it being compile-time-configurable, write out the SystemdService
line if and only if you are going to install the systemd unit - but I personally think that's unnecessary complexity, particularly in a project not using Autoconf or similar. Installing the systemd unit unconditionally doesn't harm non-systemd users other than by having an unused file present, in the same way that installing the man page doesn't harm people who don't read man pages.)
Other than that, the code provided by dunst will only fail if the OS Integrator has provided something inconsistent
At the moment dunst is not internally consistent: it always tells dbus-daemon to use systemd for activation if possible, but then does not install the necessary file for that systemd activation to work.
dbus-daemon does not check that the referenced SystemdService
exists before delegating activation to systemd - it cannot, because it does not know which directories systemd is going to search.
So, in short, the things that need to be done to close this are:
/usr/lib/systemd/user/dunst.service
(via make install
).Always install the dunst.service file into /usr/lib/systemd/user/dunst.service (via make install)
this should account for PREFIX
, too?
Yes, you're correct, it should.
this should account for PREFIX, too?
Yes, but use ${prefix}/lib
, not ${libdir}
. systemd always looks for units in lib
, even on systems where shared libraries etc. would go in a parallel directory like lib64
or lib/x86_64-linux-gnu
.
One of the concerns I have with setting up dunst as a systemd service by default is that according to my tests, if dunst crashes for any reason dbus will happily restart it when the next notification goes through while it causes a hang and timeout if dunst is configured as a systemd service and it's in failed state.
A solution might be to set Restart=on-failure
but I am not sure about how effective that would be since it depends on a timeout and I can't seem to find a way to set it so that it only restarts from a dbus activation.
Setting a timeout is a valid option but if it continuously crashes for one reason on another(i.e. X server hasn't been started yet) can cause quite a bit of log spam.
One of the concerns I have with setting up dunst as a systemd service by default is that according to my tests, if dunst crashes for any reason dbus will happily restart it when the next notification goes through while it causes a hang and timeout if dunst is configured as a systemd service and it's in failed state.
I just tested that, and that doesn't seem to be so:
pkill -KILL dunst
.notify-send asdf
Setting a timeout is a valid option but if it continuously crashes for one reason on another(i.e. X server hasn't been started yet) can cause quite a bit of log spam.
Doesn't the graphical.session.target
thing mentioned here cover that?
I just tested that, and that doesn't seem to be so
You're right, I assumed that systemd was the cause but apparently not. After a bit more testing it seems that what I mentioned happens because I set dunst to fail on startup to test this(by disabling the display server) and dbus doesn't acknowledge that the activation failed and causes all messages to that address to hang until it times out.
Doesn't the graphical.session.target thing mentioned here cover that?
According to the man page
This target is active whenever any graphical session is running. It is used to stop user services which only apply to a graphical (X, Wayland, etc.) session when the session is terminated.
So it's only for stopping it, it doesn't set a dependency on it. I am not sure what would be the correct way to set a hard dependency on the display server.
So it's only for stopping it, it doesn't set a dependency on it. I am not sure what would be the correct way to set a hard dependency on the display server.
From man systemd.unit
:
BindsTo= Configures requirement dependencies, very similar in style to Requires=. However, this dependency type is stronger: in addition to the effect of Requires= it declares that if the unit bound to is stopped, this unit will be stopped too. This means a unit bound to another unit that suddenly enters inactive state will be stopped too. Units can suddenly, unexpectedly enter inactive state for different reasons: the main process of a service unit might terminate on its own choice, the backing device of a device unit might be unplugged or the mount point of a mount unit might be unmounted without involvement of the system and service manager.
When used in conjunction with After= on the same unit the behaviour of BindsTo= is even stronger. In this case, the unit bound to strictly has to be in active state for this unit to also be in active state. This not only means a unit bound to another unit that suddenly enters inactive state, but also one that is bound to another unit that gets skipped due to a failed condition check (such as ConditionPathExists=, ConditionPathIsSymbolicLink=, ... — see below) will be stopped, should it be running. Hence, in many cases it is best to combine BindsTo= with After=.
TBH, I wouldn't worry too much about this though; if an application tries to send a notification when the display server is not running, it's expected to fail.
Actually, come to think about it, BindsTo
isn't such a good idea: if an application queries the notification server, it'll start the desktop environment. This is undesirable.
Bah, scrub all that, we were discussing PartOf
, not BindsTo
, I got my shit mixed up.
I think PartOf
is enough: stop the dunst when the graphical environment stops. Trying to send notifications when no graphical environment is running should fail, and I don't think that scenario requires extra consideration.
Trying to send notifications when no graphical environment is running should fail, and I don't think that scenario requires extra consideration.
You're right, what I said before was with the erroneous assumption that systemd didn't restart failed units.
Please add the PartOf
line to #324. I'll update the Makefile to install the systemd service file once that's merged.
Closed via #324
Hi,
I bumped into the above described problem in the following way:
I run latest dunst, which includes the changes made in #324
Thank you
How is it in a failed
state before any notification is sent?
It's activated by DBus when the first notification arrives.
Actually, I just realised the service can be configured to auto-start on login, but it also starts before the graphic session.
There's probably two fixes around this:
WantedBy
, so running systemd --user enable dunst
refuses to link it. This probably makes sense the most, as dunst will get auto-started by dbus when it's needed.WantedBy
to PartOf=graphical-session.target
, so that at least it gets delayed until a graphical session is up. It's hard to see a reason to do this though.Hmmmm, I went for the first workaround but did not worked at all.
Failed state remains with journalctl stating
Mar 19 18:18:41 hecate systemd[861]: Starting Dunst notification daemon...
Mar 19 18:18:41 hecate dunst[880]: CRITICAL: Cannot open X11 display.
Mar 19 18:18:41 hecate systemd[861]: dunst.service: Main process exited, code=exited, status=1/FAILURE
Should I post --full
?
To expand on the above: that’s the failed state after reboot and login.
What's the output of systemctl --user status dunst
?
The following after boot and log into the X session:
● dunst.service - Dunst notification daemon
Loaded: loaded (/home/manuel/.config/systemd/user/dunst.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Thu 2020-03-19 19:55:19 EET; 1min 16s ago
Docs: man:dunst(1)
Process: 905 ExecStart=/usr/bin/dunst (code=exited, status=1/FAILURE)
Main PID: 905 (code=exited, status=1/FAILURE)
Mar 19 19:55:19 hecate systemd[886]: Starting Dunst notification daemon...
Mar 19 19:55:19 hecate dunst[905]: CRITICAL: Cannot open X11 display.
Mar 19 19:55:19 hecate systemd[886]: dunst.service: Main process exited, code=exited, status=1/FAILURE
Mar 19 19:55:19 hecate systemd[886]: dunst.service: Failed with result 'exit-code'.
Mar 19 19:55:19 hecate systemd[886]: Failed to start Dunst notification daemon.
It seems that somehow dunst have been set to auto-start on login, rather that with dbus-activation.
systemctl --user disable dunst
should do the trick.
Mmmm, it does not affect in any way. After disabling dunst, on reboot the system remains in failed state.
When issuing a notification, then (I assume) dbus starts the service and the system recovers. I assume it is nitpicking, at this point.
But I am still intrigued on the why.
This is odd. Is it still autostarting early? What's the output of systemctl --user status dunst
now?
What about find .config/systemd -iname "*dunst*"
?
systemctl reports the following state for dunst
● dunst.service - Dunst notification daemon
Loaded: loaded (/usr/lib/systemd/user/dunst.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Fri 2020-03-20 12:16:13 EET; 9s ago
Docs: man:dunst(1)
Process: 904 ExecStart=/usr/bin/dunst (code=exited, status=1/FAILURE)
Main PID: 904 (code=exited, status=1/FAILURE)
Mar 20 12:16:13 hecate systemd[885]: Starting Dunst notification daemon...
Mar 20 12:16:13 hecate dunst[904]: CRITICAL: Cannot open X11 display.
Mar 20 12:16:13 hecate systemd[885]: dunst.service: Main process exited, code=exited, status=1/FAILURE
Mar 20 12:16:13 hecate systemd[885]: dunst.service: Failed with result 'exit-code'.
Mar 20 12:16:13 hecate systemd[885]: Failed to start Dunst notification daemon.
And find does not find anything under .config/systemd
For completeness:
$ systemctl --user cat dunst.service
# /usr/lib/systemd/user/dunst.service
[Unit]
Description=Dunst notification daemon
Documentation=man:dunst(1)
PartOf=graphical-session.target
[Service]
Type=dbus
BusName=org.freedesktop.Notifications
ExecStart=/usr/bin/dunst
[Install]
# WantedBy=default.target
I'm a bit confused as to why it still says disabled. systemctl --user disable dunst
did disable it, right?
What distribution is this on? Is it force-enabled system-wide? tree /etc/systemd/user/
?
Yeah, it is disabled, no link under .config/systemd/user
It is a netinst of Debian Testing.
$ tree /etc/systemd/user
/etc/systemd/user
├── default.target.wants
│ ├── dunst.service -> /usr/lib/systemd/user/dunst.service
│ └── pulseaudio.service -> /usr/lib/systemd/user/pulseaudio.service
└── sockets.target.wants
├── dirmngr.socket -> /usr/lib/systemd/user/dirmngr.socket
├── gpg-agent-browser.socket -> /usr/lib/systemd/user/gpg-agent-browser.socket
├── gpg-agent-extra.socket -> /usr/lib/systemd/user/gpg-agent-extra.socket
├── gpg-agent.socket -> /usr/lib/systemd/user/gpg-agent.socket
├── gpg-agent-ssh.socket -> /usr/lib/systemd/user/gpg-agent-ssh.socket
├── pk-debconf-helper.socket -> /usr/lib/systemd/user/pk-debconf-helper.socket
└── pulseaudio.socket -> /usr/lib/systemd/user/pulseaudio.socket
2 directories, 9 files
/etc/systemd/user
├── default.target.wants
│ ├── dunst.service -> /usr/lib/systemd/user/dunst.service
The service was enabled system-wide by the Debian packaging, because at the time it was installed, it had WantedBy=default.target
(which I think is a bug - it shouldn't be started before the GUI, and in any case shouldn't be started for users of other Notifications implementations, like GNOME Shell). Disabling it per-user does not disable it system-wide.
You're right @smcv, thanks for tracking it down @WhyNotHugo @magandrez. I've now removed the WantedBy
line with 43c6145
I have a question. Now dunst
is static. But dbus --session
can't run it because there is no DISPLAY
variable. How do I install it there? Is this a distribution setup problem or yours (dbus
is not a graphical application, should there be a DISPLAY
in principle?)? My by it works only on specific DM?
Manjaro
LightDM==1:1.30.0-4
i3-gaps==4.18.2-2
dusnt==1.5.0-1.0
dbus==1.12.20-1
p.s. I know that i can use systemctl --user start {}
fwiw; after an upgrade to Ubuntu 20.04 from 18.04, hit this bug;
ii dunst 1.4.1-1 amd64 dmenu-ish notification-daemon
In a comment @nmschulte mentioned that the dbus service file fails to launch dunst if the service file is not installed.
This only happens if dbus is started with the
--systemd-activation
flag and it looks like in that case if the service file is not found it ignores theExec
line. We should eitherSystemdService
line from the dbus service file, essentially not allowing dunst to be managed by systemd by default orAs an additional sidenote that is loosely within the scope of this issue, @mathstuf linked an issue in the same thread that apparently systemd dbus units look in the system bus rather than the session bus as they should. We should