9 ms·
Beyond Ctrl-C: The dark corners of Unix signal handling
- chrsig 2y agoMy favorite signal surprise was running nginx and/or httpd in the foreground and wondering why on earth it quit whenver i resized the window. Turns out, they use SIGWINCH (which is sent on WINdow CHange) for graceful shutdown. It's a silly, silly problem.
- eadmund 2y ago> Turns out, they use SIGWINCH (which is sent on WINdow CHange) for graceful shutdown. That’s … that’s even worse than people who send errors with an HTTP 200 response code.
- chrsig 2y agoy'know...what really is an error, anyway?
- thebruce87m 2y agoFor what is an error, if not a success at failing?
- chrsig 2y agoExactly. Gotta be happy you got a response at all!
- AStonesThrow 2y agoIn my day, successful commands output nothing at all, so it would seem that a blank page is the only truly error-free result.
- aunderscored 2y agoDisagree. Annoyingly there is a reasonable case for 200 but with an error, if http is your transport but not your application, then 200 says "yes, the message was transfered and understood correctly, here is your response" which may be an error response from the application
- Izkata 2y agoFor example: Apache (httpd) replaces the 4xx and 5xx response body with its own content instead of whatever you'd returned from an external handler like wsgi. You have to use a 2xx (except for 204) to get a relevant error message back out.
- AdieuToLogic 2y ago> For example: Apache (httpd) replaces the 4xx and 5xx response body with its own content instead of whatever you'd returned from an external handler like wsgi. 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. HTH 0 - https://httpd.apache.org/docs/trunk/custom-error.html https://httpd.apache.org/docs/trunk/custom-error.html
- jjnoakes 2y agoEven with custom error documents configured in the web server, you still lose the application-specific (and probably request- and error-specific) message generated by the application itself.
- Izkata 2y agoYeah, this is how we ran across it - whoever originally wrote a particular feature was trying to do the right thing by using an HTTP error code, but with a message that would be presented to the user about why that operation failed. A generic response wouldn't work, there were multiple possible reasons all fixable by the user, and tying a whole error code to one specific feature would've probably been a bad idea anyway.
- thezilch 2y agoThat's ... not what most people are doing. People send _application_ errors on HTTP 200 response codes, because HTTP response codes are for HTTP and not applications. Most "REST" libraries and webdev get this wrong, building ever more fragile web services.
- ChocolateGod 2y agoApplications using status codes is useful because it can tell browsers and load balancers to not cache the page in a uniform way.
- LoganDark 2y agoTask failed successfully
- sunshowers 2y agoI don't think the distinction is as clear-cut as you're making it out to be. For 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).
- thayne 2y agoWhy? That's what SIGTERM is for.
- chrsig 2y agoNo clue what the decision making process was. 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 https://bz.apache.org/bugzilla/show_bug.cgi?id=50669 [1] https://mailman.nginx.org/pipermail/nginx/2011-August/028640.html https://mailman.nginx.org/pipermail/nginx/2011-August/028640...
- hulitu 2y ago> why on earth would it get a SIGWINCH!? Reminds me of those "/* not reached */" stories.
- ibash 2y agoI tried to find out why. 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/5238e93961a189c13eefff01f8eccfe863159c72/nginx https://trac.nginx.org/nginx/changeset/5238e93961a189c13eeff...
- chrsig 2y agook, I found a commit in 2005, coming about because linuxthreads was interfering with the SIGUSR1 signal. 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/395896ae8d19bbea10f82b1d40e16f4721d316b7 https://github.com/apache/httpd/commit/395896ae8d19bbea10f82...
- ykonstant 2y agoI don't know whether to laugh or cry.
- chrsig 2y agodefinitely laugh! life's too short, you'll never get out alive :)
- deleted 2y ago[deleted]
- efxhoy 2y agoI recently wrote a little data transfer service in python that runs in ECS. When developing it locally it was easy to handle SIGINT: try write a batch, except KeyboardInterrupt, if caught mark the transfer as incomplete and finally commit the change and shut down. 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.
- Spivak 2y agoI mean you can just have the signal handler throw StopRequested in your Python boilerplate and never think about it again. One common pattern is raising KeyboardInterrupt from your handler so it's all handled the same.
- mananaysiempre 2y agofrom 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)
- layer8 2y ago> Another common extension is to use what is sometimes called a double Ctrl-C pattern. The first time the user hits Ctrl-C, you attempt to shut down the database cleanly, but the second time you encounter it, you give up and exit immediately. 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).
- bcrl 2y agoThat shouldn't matter. Your database should be consistent in the face of an unclean exit. ACID has been around for a long time.
- tripdout 2y agoIf you don't know about it, sure, but I find it's kind of convenient to get a safe shutdown and then be able to easily say "I don't care, just stop this program" without needing a separate kill -9 command or something.
- layer8 2y agoAs I wrote, Ctrl-\ should do the trick. And it’s just not practical having to know which program applies the double pattern, and having to train yourself to not accidentally hit Ctrl-C twice.
- __MatrixMan__ 2y agoMy brush with the double-ctrl-C pattern was in a place that wrote a lot of Java. It was generally frowned on to write any code that relied on signals which windows users can't send, and if I recall, Java made it quite difficult anyhow. 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.
- 2y ago
- cperciva 2y agoThe article doesn't mention the most useful of all signals: SIGINFO, aka "please print to stderr your current status". Very useful for tools like dd and tar. 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.
- fragmede 2y agodd prints out status when sent SIGUSR1, but yeah that would be cool if other utilities did that as well off SIGINFO.
- cperciva 2y agoAnd does ^T map to SIGUSR1? That's the other thing which makes it so useful in BSD.
- epcoa 2y ago> 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 https://cr.yp.to/docs/selfpipe.html
- 2y ago