Turns out, they use SIGWINCH (which is sent on WINdow CHange) for graceful shutdown.
It's a silly, silly problem.
That’s … that’s even worse than people who send errors with an HTTP 200 response code.
If, OTOH, your application is a hypermedia application, then returning a success status for errors is just wrong.
This is the default behavior. Apache httpd can be configured to produce different responses by way of ErrorDocument[0]. From the documentation:
Customized error responses can be defined for any HTTP
status code designated as an error condition - that is,
any 4xx or 5xx status.
HTHFor example, HTTP 409 Conflict generally means an application-level conflict (e.g. an optimistic concurrency mechanism detected a conflict).
HTTP 422 Unprocessable Entity is also usually an application-level error (e.g. hash validation failure, or identifier not recognized by the server).
There's a bug report for httpd dating back to 2011[0]. The nginx mailling list also has a grumpy person contemporary with that[1].
My guess is someone thought "httpd is a server running somewhere without a monitor attached, why on earth would it get a SIGWINCH!? surely it's available to use for something completely different", not considering users running it in the foreground during development. Nginx probably followed suit for convention, but that's pure speculation on my part.
Also that was before docker really took off (I'm not sure if it was around in 2011 yet; still in it's infancy maybe). Running it in the foreground didn't happen as much yet. People were still using wamp or installing it via apt and restarting via sudo.
[0] https://bz.apache.org/bugzilla/show_bug.cgi?id=50669
[1] https://mailman.nginx.org/pipermail/nginx/2011-August/028640...
Reminds me of those "/* not reached */" stories.
SIGWINCH is apparently used for an online upgrade [1]. Because it only shuts the workers down you can quickly transition back to the old binary and old configuration if there's a problem, even after upgrading the binary or config stored on the hard drive.
I'm sure there are other ways to get a similar capability, but this set of signals is apparently what they came up with.
[0] http://nginx.org/en/docs/dev/development_guide.html#processe...
[1] https://www.digitalocean.com/community/tutorials/how-to-upgr...
Unfortunately the change that introduces it predates the official release by a few months. And predates the mailing list by about a year:
https://trac.nginx.org/nginx/changeset/5238e93961a189c13eeff...
It looks like they wound up making it platform specific, so BSDs and unix like operating systems might still use SIGUSR1.
https://github.com/apache/httpd/commit/395896ae8d19bbea10f82...
This is a terrible behavior, because users tend to hit Ctrl-C multiple times without intending anything different than on a single hit (not to mention bouncing key mechanics and short key repeat delays). Unclean exits should be reserved for SIGQUIT (Ctrl-\) and SIGKILL (by definition).
Subject: -42- How can I restart the X server? Date: 10 Sep 1995 00:00:01 EST
To restart the X server (Xsgi) once, do any one of the following
(in increasing order of brutality):
- killall -TERM Xsgi
- hold down the left-Control, left-Shift, F12 and keypad slash keys
(this is fondly known as the "Vulcan Death Grip")
- /usr/gfx/stopgfx; /usr/gfx/startgfx
- reboot
To restart the X server every time someone logs out of the console,
edit /var/X11/xdm/xdm-config, change the setting of
"DisplayManager._0.terminateServer" from "False" to "True" and do
'killall -HUP xdm'.
Windows does have a tradition of using ctrl-c to quit though, so SIGINT ends up being one of the few that you can use in both places. It's not pretty, but giving it a different meaning based on how many times you've ordered it seems like a somewhat natural next step, if a hacky one.
However, in both cases it's a clean shutdown, all running are terminated and the test report is printed.
I don't know how it works on your keyboard but on french layout, Ctrl-\ is a two-hands, three-fingers, very unpleasant on the wrist, keyboard shortcut. Not a chance I'd use that for such a common operation.
Ctrl-2 = Ctrl-@ = NUL byte
Ctrl-3 = Ctrl-[ = ESC
Ctrl-4 = Ctrl-\ = default for SIGQUIT
Ctrl-5 = Ctrl-] = jump to definition in vim
Ctrl-6 = Ctrl-^ = mosh escape key
Ctrl-7 = Ctrl-_ = undo in Emacs
I think these probably originate in xterm.
Make sure that thing is disabled
We have a right Ctrl, so one-hand two-finger.
What means that you have to memorize a list of "oh, this program needs Ctrl-C 3 times; oh, this program must only receive Ctrl-C once!"... I don't know of any "oh, this program needs Ctrl-C exactly 2 times", but it's an annoying possibility.
Hence you can just press it once and wait half a second, if no message to this effect appears you can spam ctrl-c.
Probably because Linux doesn't implement it. Worst mistake Linus ever made.
Also, it talks about self-pipe but doesn't mention that self-socket is much better since you can't select on a pipe.
This needs further explanation. Why can’t you select on a pipe? You certainly can use select/poll on pipes in general and I’m not sure of any reason in particular they won’t work for the self pipe notification.
Its even right in the original: https://cr.yp.to/docs/selfpipe.html
Yes, you can select just fine on pipes. What I was thinking of is that recv and send doesn't work on pipes, and asynchronous I/O frameworks typically want to use send/recv rather than write/read because the latter don't have a flags parameter.
For most users in the real world, self-pipes are sufficient. This includes mio (Tokio's underlying library)'s portable Unix implementation of wakers (how parts of the system tell other parts to wake up).
SIGSTOP is the equivalent of Ctrl-Z in a shell, but you can address it to any process. If you have a server being bogged down, you can stop the offending process temporarily.
SIGCONT undoes SIGSTOP.
The cpulimit tool does this in an automated way so that a process can be limited to use x% of CPU. Nice/renice doesn't keep your CPU from hitting 100% even with an idle priority process, which may be undesirable if it drains battery quickly or makes the cooling fan loud.
I have a very exciting blog post about debugging a nasty bug with how SIGTSTP works, coming very soon.
But there’s no exception in python to catch for a SIGTERM, which is what ECS and other service mangers send when it’s time to shut down. So I had to add a signal handler. Would have been neat if SIGTERM could be caught like SIGINT with a “native” exception.
from signal import SIGTERM, raise_signal, signal
import sys # for excepthook
class Terminate(BaseException):
pass
def _excepthook(type, value, traceback):
if not issubclass(type, Terminate):
return _prevhook(type, value, traceback)
# If a Terminate went unhandled, make sure we are killed
# by SIGTERM as far as wait(2) and friends are concerned.
signal(SIGTERM, _prevterm)
raise_signal(SIGTERM)
_prevhook, sys.excepthook = sys.excepthook, _excepthook
def terminate(signo=SIGTERM, frame=None):
signal(SIGTERM, _prevterm)
raise Terminate
_prevterm = signal(SIGTERM, terminate)
One common pattern is raising KeyboardInterrupt from your handler so it's all handled the same.