Discussion:
Fwd: best way to handle service restarts after hibernate/suspend?
(too old to reply)
Mathijs Kwik
2013-08-07 08:12:02 UTC
Permalink
Hi all,

I have a few things that need to get run after waking up my laptop
(things like hdparm to set device power options/spindown time).
I created oneshot, remainafterexit services for those and made them
wanted by multi-user.target.This works fine for the first boot.

As I consider these services "dead" after a suspend/hibernate, I added
Conflicts=sleep.target, so now systemd is aware that these services
are no longer active after a wakeup.

Now I would like to somehow have these services restart on wakeup.
I can add these services to some new target(wakeup.target), but I
don't know how to proceed from there. I thought of making
wakeup.target WantedBy suspend.target, After suspend.target, but since
suspend.target pulls in sleep.target (which conflicts with these
services) that will fail. More so, after wakeup.target is started the
first time, it will never go down itself, so the second wakeup won't
do anything. The same is true for multi-user.target, once that is
reached/activated on first boot, it never deactivates until shutdown.

How should a situation like this be handled?
Ideally, I don't want to use:
- /usr/lib/systemd/system-sleep (considered hacky)
- a service/script that runs "systemctl start ..." (secret
dependency, hidden from systemd)

Thanks,
Mathijs
Tom Gundersen
2013-08-07 11:02:25 UTC
Permalink
Post by Mathijs Kwik
I have a few things that need to get run after waking up my laptop
(things like hdparm to set device power options/spindown time).
I created oneshot, remainafterexit services for those and made them
wanted by multi-user.target.This works fine for the first boot.
Are you sure you want RemainAfterExit? Without it you should be able
to set WantedBy=sleep.target and After=sleep.target.
Post by Mathijs Kwik
As I consider these services "dead" after a suspend/hibernate, I added
Conflicts=sleep.target, so now systemd is aware that these services
are no longer active after a wakeup.
Now I would like to somehow have these services restart on wakeup.
I can add these services to some new target(wakeup.target), but I
don't know how to proceed from there. I thought of making
wakeup.target WantedBy suspend.target, After suspend.target, but since
suspend.target pulls in sleep.target (which conflicts with these
services) that will fail. More so, after wakeup.target is started the
first time, it will never go down itself, so the second wakeup won't
do anything. The same is true for multi-user.target, once that is
reached/activated on first boot, it never deactivates until shutdown.
How should a situation like this be handled?
- /usr/lib/systemd/system-sleep (considered hacky)
- a service/script that runs "systemctl start ..." (secret
dependency, hidden from systemd)
Thanks,
Mathijs
_______________________________________________
systemd-devel mailing list
http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Mathijs Kwik
2013-08-07 12:00:11 UTC
Permalink
Indeed, that sounds like a solution.

It's a bit of a philosophical thing though, remainafterexit+oneshot
works nicely for things that represent a certain state (powersaving
on) which can be inspected and turned off.

oneshot "scripts" don't feel natural to me somehow without such a
state (which RemainAfterExit provides).
But maybe I need to alter my view on services a bit.

For now I will try your solution. Thanks
Post by Tom Gundersen
Post by Mathijs Kwik
I have a few things that need to get run after waking up my laptop
(things like hdparm to set device power options/spindown time).
I created oneshot, remainafterexit services for those and made them
wanted by multi-user.target.This works fine for the first boot.
Are you sure you want RemainAfterExit? Without it you should be able
to set WantedBy=sleep.target and After=sleep.target.
Post by Mathijs Kwik
As I consider these services "dead" after a suspend/hibernate, I added
Conflicts=sleep.target, so now systemd is aware that these services
are no longer active after a wakeup.
Now I would like to somehow have these services restart on wakeup.
I can add these services to some new target(wakeup.target), but I
don't know how to proceed from there. I thought of making
wakeup.target WantedBy suspend.target, After suspend.target, but since
suspend.target pulls in sleep.target (which conflicts with these
services) that will fail. More so, after wakeup.target is started the
first time, it will never go down itself, so the second wakeup won't
do anything. The same is true for multi-user.target, once that is
reached/activated on first boot, it never deactivates until shutdown.
How should a situation like this be handled?
- /usr/lib/systemd/system-sleep (considered hacky)
- a service/script that runs "systemctl start ..." (secret
dependency, hidden from systemd)
Thanks,
Mathijs
_______________________________________________
systemd-devel mailing list
http://lists.freedesktop.org/mailman/listinfo/systemd-devel
孙冰
2013-08-08 06:12:30 UTC
Permalink
I use this:
----------------------------------------
[Unit]
Description=Wicd sleep hook
Before=sleep.target
StopWhenUnneeded=yes

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=-/usr/share/wicd/daemon/suspend.py
ExecStop=-/usr/share/wicd/daemon/autoconnect.py

[Install]
WantedBy=sleep.target
-----------------------------------------
Mathijs Kwik
2013-08-08 06:32:34 UTC
Permalink
Post by 孙冰
----------------------------------------
[Unit]
Description=Wicd sleep hook
Before=sleep.target
StopWhenUnneeded=yes
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=-/usr/share/wicd/daemon/suspend.py
ExecStop=-/usr/share/wicd/daemon/autoconnect.py
[Install]
WantedBy=sleep.target
-----------------------------------------
Clever :)

It turns out I always misinterpreted the documentation for
StopWhenUnneeded. I never read past the first sentence and assumed this
option was only going to stop services "when it felt like it".

But this is a very nice solution, still stateful (remainafterexit) but
by focusing on the sleep-state instead of the before-sleep and
after-sleep it nicely works around cyclic/conflicting dependencies.

Thanks!
killermoehre
2013-08-08 10:16:46 UTC
Permalink
Post by 孙冰
----------------------------------------
[Unit]
Description=Wicd sleep hook
Before=sleep.target
StopWhenUnneeded=yes
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=-/usr/share/wicd/daemon/suspend.py
ExecStop=-/usr/share/wicd/daemon/autoconnect.py
[Install]
WantedBy=sleep.target
-----------------------------------------
Thank you very much for this idea. I think it can be expressed in a more
generic way:

----------------------------------------
[Unit]
Description=%I sleep hook
Before=sleep.target
StopWhenUnneeded=yes

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=-/usr/bin/systemctl stop %I
ExecStop=-/usr/bin/systemctl start %I

[Install]
WantedBy=sleep.target
-----------------------------------------

It would be invoked from sleep-***@.service.
What do you think?
孙冰
2013-08-08 11:07:38 UTC
Permalink
Hi,

Yep. I have the exact same ***@.service and it works.

BTW, sleep.target is pulled in by both suspend.target and
hibernate.target. There are some use cases that a hook should be only
invoked by suspend.target (or hibernate.target). For instance, I have a
hook used with the tuxoniceui:

----------------------------------------------------
[Unit]
Description=tuxoniceui hibernate hook
Before=hibernate.target
StopWhenUnneeded=yes

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/bin/bash -c "echo `fgconsole` > %t/tuxoniceui"
ExecStart=/bin/chvt 63
ExecStop=-/bin/bash -c "chvt `< %t/tuxoniceui`"
ExecStopPost=-/bin/rm -rf %t/tuxoniceui

[Install]
WantedBy=hibernate.target

----------------------------------------------------

Obviously I don't want it to be called for suspend.target. The problem
is, by default, suspend.target/hibernate.target is not a
StopWhenUnneeded service. I have to overwrite it in
/etc/systemd/system/hibernate.target.d. It's completely OK for me to do
this. What I wonder is, what is the reason by they are not
StopWhenUnneeded services?

Uh, seems overly off-topic...

Regards.
Lennart Poettering
2013-08-09 15:46:50 UTC
Permalink
Post by Mathijs Kwik
Hi all,
I have a few things that need to get run after waking up my laptop
(things like hdparm to set device power options/spindown time).
I created oneshot, remainafterexit services for those and made them
wanted by multi-user.target.This works fine for the first boot.
As I consider these services "dead" after a suspend/hibernate, I added
Conflicts=sleep.target, so now systemd is aware that these services
are no longer active after a wakeup.
Now I would like to somehow have these services restart on wakeup.
I can add these services to some new target(wakeup.target), but I
don't know how to proceed from there. I thought of making
wakeup.target WantedBy suspend.target, After suspend.target, but since
suspend.target pulls in sleep.target (which conflicts with these
services) that will fail. More so, after wakeup.target is started the
first time, it will never go down itself, so the second wakeup won't
do anything. The same is true for multi-user.target, once that is
reached/activated on first boot, it never deactivates until shutdown.
How should a situation like this be handled?
- /usr/lib/systemd/system-sleep (considered hacky)
Well, doing hdparm fiddling after suspend is a hack in itself, hence
/usr/lib/systemd/system-sleep/ is precisely the right hacky choice to
implement something like this. It's simple, synchronous and the intended
place to put hacks like this.

Lennart
--
Lennart Poettering - Red Hat, Inc.
Loading...