Description of problem: httpd.service sends SIGWINCH to $MAINPID in ExecStop. This means that httpd should shutdown gracefully [1]. However, systemd sends SIGTERM *right* after ExecStop execution without any configurable timeout. Httpd does not have any time to shutdown gracefully or to do some cleanup and receives SIGTERM. I think there should be some timeout to set delay between these two actions. The true is that httpd should ignore SIGTERM when SIGWINCH is handled. I'm working with upstream on fix for this, but I think it's still not ideal behaviour. [1] http://httpd.apache.org/docs/2.2/stopping.html#gracefulstop
The ExecStop action ought to be synchronous. I.e. the service should be already stopped by the time ExecStop finishes.
This is what systemd.service(5) says: TimeoutStopSec= Configures the time to wait for stop. If a service is asked to stop but does not terminate in the specified time, it will be terminated forcibly via SIGTERM, and after another delay of this time with SIGKILL (See Is the man page wrong? It says the SIGTERM is sent *after* a timeout.
(In reply to comment #0) > Description of problem: > httpd.service sends SIGWINCH to $MAINPID in ExecStop. Would it solve your problem if instead of defining an ExecStop action you'd set "KillSignal=SIGWINCH" ? See systemd.kill(5). (In reply to comment #2) > Is the man page wrong? It says the SIGTERM is sent *after* a timeout. Not wrong, but apparently unclear. The timeout limits the time the ExecStop action is allowed to run. There are two actual systemd issues: 1) The start timeout is applied by mistake in one place where the stop timeout should be used. 2) The documentation should be improved. Perhaps a man page describing the service state machine would help answer questions like this. [ Reopening to resolve 1) ].
(In reply to comment #3) > Would it solve your problem if instead of defining an ExecStop action you'd > set "KillSignal=SIGWINCH" ? See systemd.kill(5). No, because this would send SIGWINCH to all processes in control-group. I need to send it just to main process but in the same time, I want SendSIGKILL to be sent to all processes (and not just to main process), otherwise children processes would remain running after systemctl stop if something went wrong during SIGWINCH handling. So far I'm using this to "fix" it: ExecStop=/usr/sbin/httpd $OPTIONS -k graceful-stop # We want systemd to give httpd some time to finish gracefully, but still want # it to kill httpd after TimeoutStopSec if something went wrong during the # grafecul stop. Normally, Systemd sends SIGTERM signal right after the # ExecStop, which would kill httpd. We are sending useless SIGCONT here to give # httpd time to finish. KillSignal=SIGCONT
I must say it seems odd to expect ExecStop to be synchronous. Most daemon packages will surely implement this by sending some async signal to the parent. What are we supposed to do instead? wait() for the parent to die? Could we provide a shell script which does #!/bin/sh kill $1 wait $1 and then use that in ExecStop to work around this?
(In reply to comment #4) Thanks for the explanation. Let's see if we can come up with nicer support for this usecase in systemd upstream. (In reply to comment #5) "wait" won't work on a PID that's not a child of the shell.
(In reply to comment #5) > I must say it seems odd to expect ExecStop to be synchronous. Most daemon > packages will surely implement this by sending some async signal to the > parent. What are we supposed to do instead? wait() for the parent to die? Well, what you do in ExecStop= already had to be synchronous in old sysv, because "service foobar stop ; service foobar start" wouldn't work correctly otherwise. > Could we provide a shell script which does > > #!/bin/sh > kill $1 > wait $1 > > and then use that in ExecStop to work around this? start-stop-daemon can do that, which is why people used that on SysV.
(In reply to comment #4) > No, because this would send SIGWINCH to all processes in control-group. I > need to send it just to main process but in the same time, I want > SendSIGKILL to be sent to all processes (and not just to main process), > otherwise children processes would remain running after systemctl stop if > something went wrong during SIGWINCH handling. This indeed sounds like a good usecase and we should provide something for this in systemd. Maybe SendSIGKILL should also accept "control-group" and "process" as arguments. Hence: SendSIGKILL=no # don't send SIGKILL SendSIGKILL=yes # send SIGKILL to the same as set with KillMode= SendSIGKILL=control-group # send SIGKILL to the entire control group SendSIGKILL=process # Send SIGKILL to the main process only I think this would be a pretty natural extension of the current logic.
Thanks, this would fix our problem.
Just adding myself to CC, but as I don't see any back reference to the bug that caused this one to be opened, here it is: https://bugzilla.redhat.com/show_bug.cgi?id=912288
This is fixed in git as "KillMode=mixed".
This message is a notice that Fedora 19 is now at end of life. Fedora has stopped maintaining and issuing updates for Fedora 19. It is Fedora's policy to close all bug reports from releases that are no longer maintained. Approximately 4 (four) weeks from now this bug will be closed as EOL if it remains open with a Fedora 'version' of '19'. Package Maintainer: If you wish for this bug to remain open because you plan to fix it in a currently maintained version, simply change the 'version' to a later Fedora version. Thank you for reporting this issue and we are sorry that we were not able to fix it before Fedora 19 is end of life. If you would still like to see this bug fixed and are able to reproduce it against a later version of Fedora, you are encouraged change the 'version' to a later Fedora version prior this bug is closed as described in the policy above. Although we aim to fix as many bugs as possible during every release's lifetime, sometimes those efforts are overtaken by events. Often a more recent Fedora release includes newer upstream software that fixes bugs or makes them obsolete.