Bug 999525

Summary: Allow system-sleep resume scripts to be non-blocking or at least spawn background tasks
Product: [Fedora] Fedora Reporter: Kamil Páral <kparal>
Component: systemdAssignee: systemd-maint
Status: CLOSED RAWHIDE QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 19CC: harald, johannbg, lnykryn, msekleta, plautrba, systemd-maint, vpavlin, zbyszek
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2013-08-21 17:23:32 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:

Description Kamil Páral 2013-08-21 13:31:31 UTC
Description of problem:
"man systemd-sleep" says:
> All executables in this directory are executed in parallel, and execution
> of the action is not continued until all executables have finished.

It makes sense to wait for all scripts to finish during system suspend, yes. But do they have to be blocking even during system resume? I have several use cases in which I'd love to have non-blocking resume scripts:

1. I have some short-running resume scripts, for example a script that uses hdparm to set sane power-management settings to my HDD (because the vendor defaults are really bad). It is executed in a second, very quick. But I don't need this to be a blocking call, I'd be very happy to have this running in parallel with the system resume procedures and not wait for it. If I were able to make it non-blocking, I'd have my wifi reconnected a second earlier (currently network initialization waits for the systemd-sleep scripts to finish). Systemd is based on the "proper design" principle, which makes the system behave quick. It seems to me that this is exactly the proper design - let's not delay my network just because I need HDD power management settings adjusted.

2. I have some long-running resume scripts (ten seconds or more). One of them was a workaround for bug 866212 (which should be hopefully resolved now) - a long standing kernel problem that killed my battery life on resume if undetected. I used the script to collect powertop data over several seconds, and alert me if the kernel bug was triggered. Again, I don't need to block the resume procedures with this. I certainly don't want to wait 15 more seconds for my wifi to connect every time I resume my laptop. But I need to run this script on every resume, otherwise my battery will get depleted very quickly without me noticing it.

I tried to work around systemd constraints by spawning background tasks inside the resume scripts. Unfortunately, it seems that systemd kills all child processes once the parent script has finished.

I know that I can write a dbus listener that will run the whole time and wait for system resume signal and then run the task I need, but this is firstly much more complicated, and secondly it wastes some resources - the script needs to run (and listen) the whole time, instead of just running once per resume.

Please, give us some way (any way) to run non-blocking scripts during system resume.

Could you please consider following ideas?

a) Allow a particular script to be non-blocking during resume, by marking it in same way as such.

-or-

b) Allow all scripts to be non-blocking during resume (but blocking during suspend, of course).

-or-

c) Consider all scripts to be blocking during both suspend and resume, but allow scripts to spawn background tasks during resume (i.e. don't kill their children processes once the scripts finish).

What do you think?


Version-Release number of selected component (if applicable):
systemd-204-9.fc19.x86_64

How reproducible:
always

Steps to Reproduce:
1. put this script into /usr/lib/systemd/system-sleep/foo.sh
#!/bin/sh
case $1/$2 in
  post/*)
    sleep 15
    ;;
esac
2. see that your network reconnects no sooner than after 15 seconds after resume
-or-
1. put this script into /usr/lib/systemd/system-sleep/bar.sh
#!/bin/sh
case $1/$2 in
  post/*)
    for i in {1..100}; do touch /tmp/bar$i; sleep 0.1; done &
    sleep 3
    ;;
esac
2. see that there is /tmp/bar30 after resume, but no /tmp/bar40, meaning that the background process was killed

Comment 1 Harald Hoyer 2013-08-21 14:11:27 UTC
why not call "systemctl --no-block start somequirk.service" from such a script?

Comment 2 Jóhann B. Guðmundsson 2013-08-21 14:16:35 UTC
Or call this directly via udev rules or have those workaround fixed upstream ;)

Comment 3 Kamil Páral 2013-08-21 14:31:58 UTC
Yes, there are other ways of handling this. Like writing my own service file or writing an udev rule. But most guys can't do that (me neither), and that's why I ask for a simple solution using simple shell scripts. There is only one piece missing, background tasks.

Sure, we can all study advanced system internals, and we will have to, if there is no simpler way.

As for having the bugs fixed, yes, that's a good (naive) idea, but that's just my use case. I'm sure there are dozens of valid use cases which are not related to hardware of software problems.

Comment 4 Zbigniew Jędrzejewski-Szmek 2013-08-21 17:23:32 UTC
You can launch a script with systemd-run, without needing to write a service file (systemd >= 205). This gives you a background task with nice control over it.

Comment 5 Kamil Páral 2013-08-22 11:43:34 UTC
(In reply to Zbigniew Jędrzejewski-Szmek from comment #4)
Amazing, thanks. I'll try that once F20 is stable enough to run on my hardware.