2

Short version: How can I get a systemd controlled service to trigger an immediate shutdown?


I have a daemon empowered to do arbitrary things in response to certain events via a (fork/exec'd) shell script ending with

exec halt -p

Or more specifically, exec $@, but in this case $@ is halt -p. I've also tried:

  • shutdown now
  • systemctl halt.

While this works, there seems to be a problem that causes the shutdown, which would normally only take a few seconds, to take several minutes. I suspect it is because systemd is waiting on a child process of a service (the halt itself) that doesn't politely die upon request. I.e., it is sort of a snake chasing its own tail scenario.

The service has no ExecStop and is Type=forking.

  • Normally, having RemainAfterExit=yes in the [Service] section of the Unit should stop it being killed on halt, but perhaps it interferes with your Type=forking detection of failure. – meuh Oct 2 '16 at 15:47
  • @meuh By the man page what that does is specify "whether the service shall be considered active even when all its processes exited", which seems very different from stopping them from "being killed on halt" (a bit oxymoronical). There should be some means by which a systemd service can trigger a shutdown. Anyway, it did not work in this case. – goldilocks Oct 2 '16 at 16:27
  • You could look through man systemd.kill and perhaps reduce TimeoutStopSec=90 or try SendSIGKILL=no. – meuh Oct 2 '16 at 16:48
  • @meuh \O/ So KillMode=process from that man page works (I imagine KillMode=none would also work, but since the daemon isn't concerned about orphans, it can be stopped). I've edited this a bit since realizing the problem was a delay, presumably in "the snake chasing its tail" (see above). Anyway, I think you get what's going and if you want to put that into an answer you can have a tick from me. No rush and if not, no worries, I'll do it later. – goldilocks Oct 2 '16 at 16:58
0

In man systemd.kill there's the following explanation of the KillMode option:

KillMode=

Specifies how processes of this unit shall be killed. One of control-group, process, mixed, none.

If set to control-group, all remaining processes in the control group of this unit will be killed on unit stop (for services: after the stop command is executed, as configured with ExecStop=).

This implies a customized ExecStop all by itself will not help, but:

If set to process, only the main process itself is killed.

If set to none, no process is killed. In this case, only the stop command will be executed on unit stop,

So, ExecStop could be used in conjunction with KillMode=none. This would be necessary if the daemon started persistent processes, to target them but not the halt. In my case it doesn't, and the daemon itself has a SIGTERM handler and does not wait on children, so needs no special cleanup. Hence adding KillMode=process to the [Service] block solved the problem; the daemon is stopped, leaving the halt to complete, and the system shuts down as it normally does in a few seconds.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.