[systemd-devel] not running ExecStop= when stopping "activating" services?
alexander.nekrasov at emc.com
Fri Mar 20 09:43:54 PDT 2015
> -----Original Message-----
> From: Andrei Borzenkov [mailto:arvidjaar at gmail.com]
> Sent: Thursday, March 19, 2015 11:41 PM
> To: Nekrasov, Alexander
> Cc: systemd-devel at lists.freedesktop.org
> Subject: Re: [systemd-devel] not running ExecStop= when stopping
> "activating" services?
> В Thu, 19 Mar 2015 15:08:39 -0400
> "Nekrasov, Alexander" <alexander.nekrasov at emc.com> пишет:
> > Hi All,
> > With these settings
> > [Service]
> > ExecStart=/cli run
> > ExecStop=/cli stop
> > Type=forking
> > PIDFile=/tmp/cli.pid
> > The service is active once "cli run" exits. A call to systemctl stop
> then produces a call to "cli stop". This is as expected.
> > However if I call "systemctl stop" on this service before "cli run"
> exited, i.e., when the service is still activating, the service is
> stopped, all threads are killed off, but "cli stop" is never run.
> > Is that as intended? Why? Is there a way to change this behavior?
> This is intentional (see commit 3f6c78dc); I do not think intention was
> as much "do not run ExecStopPost" as "do not spend time if starting
> failed anyway"). There is currently no way to change it, it is
> hardcoded. I guess you will need to present use case and explain what
> is broken with current behavior.
[AN] here's the case. Often start-up of a service isn't just a one step, like starting a process. They need to bind LUNs, take locks, mount stuff, create structures, reformat DBs, create pid files, etc., before they want to report "ready" to the system. The main thing is, start-up is often a multi-step process, and the steps often make changes that are persistent. If that process is interrupted, there needs to be code run to make sure what's left is either cleaned up or made consistent. The kernel won't do the cleanup, so just killing off the processes in the c group isn't enough. The cleanup code also needs to be run after a failure, or a stop. Since systemd provides an ExecStop= option, that's an obvious place to hook cleanup code to, much like the catch section in a C++ code. But for that to be useful, we must have a guarantee that the ExecStop will be called. There are obvious exception, such as the whole node crashing, where it won't be called, but that's understood.
Other options would be 1) trapping the TERM in the ExecStart thread, but
- that means placing the same code in two locations - the term handler and the ExecStop, since it still needs to run on failre/stop
- if ExecStart is bash, which it often is, trapping TERM is unreliable - the handler won't run if the script context is in a wait() for example, or even in a sleep, until the wait/sleep exits. Which may be long after the timeout
Or 2) the code could be put into an OnFailure= unit, but
- that is more complex, requires an extra unit per each service (or a template with a switch inside)
- still placing the code into two places, OnFailure and ExecStop to handle normal stop
On the other hand, the savings that come with not running ExecStop if a service start-up is interrupted can't be major because the use case itself cannot be normal.
> Although there is obvious corner case - timeout expires exactly when
> service starts and before systemd has chance to notice it. Then we have
> fully started service that gets killed.
> > systemd-210-34.9.x86_64
> > systemd-bash-completion-210-34.9.noarch
> > systemd-rpm-macros-2-7.2.noarch
> > util-linux-systemd-2.25-2.2.x86_64
> > systemd-32bit-210-34.9.x86_64
> > systemd-sysvinit-210-34.9.x86_64
> > systemd-presets-branding-SLE-12.0-12.1.noarch
> > Thanks,
> > Alex
> > _______________________________________________
> > systemd-devel mailing list
> > systemd-devel at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/systemd-devel
More information about the systemd-devel