diff options
author | Jeff King <peff@peff.net> | 2015-05-15 02:29:27 -0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-05-15 11:13:47 -0700 |
commit | 7253a02348c1c44c84f8a13309d6d30b443bf23c (patch) | |
tree | 314496f9d5741f933e2d0b9ad15d79486849b8a7 /http-backend.c | |
parent | fdf96a20acf96a6ac538df8113b2aafd6ed71d50 (diff) | |
download | git-7253a02348c1c44c84f8a13309d6d30b443bf23c.tar.gz |
http-backend: fix die recursion with custom handler
When we die() in http-backend, we call a custom handler that
writes an HTTP 500 response to stdout, then reports the
error to stderr. Our routines for writing out the HTTP
response may themselves die, leading to us entering die()
again.
When it was originally written, that was OK; our custom
handler keeps a variable to notice this and does not
recurse. However, since cd163d4 (usage.c: detect recursion
in die routines and bail out immediately, 2012-11-14), the
main die() implementation detects recursion before we even
get to our custom handler, and bails without printing
anything useful.
We can handle this case by doing two things:
1. Installing a custom die_is_recursing handler that
allows us to enter up to one level of recursion. Only
the first call to our custom handler will try to write
out the error response. So if we die again, that is OK.
If we end up dying more than that, it is a sign that we
are in an infinite recursion.
2. Reporting the error to stderr before trying to write
out the HTTP response. In the current code, if we do
die() trying to write out the response, we'll exit
immediately from this second die(), and never get a
chance to output the original error (which is almost
certainly the more interesting one; the second die is
just going to be along the lines of "I tried to write
to stdout but it was closed").
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'http-backend.c')
-rw-r--r-- | http-backend.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/http-backend.c b/http-backend.c index b6c0484fb2..3ad82a894d 100644 --- a/http-backend.c +++ b/http-backend.c @@ -500,21 +500,24 @@ static void service_rpc(char *service_name) strbuf_release(&buf); } +static int dead; static NORETURN void die_webcgi(const char *err, va_list params) { - static int dead; + if (dead <= 1) { + vreportf("fatal: ", err, params); - if (!dead) { - dead = 1; http_status(500, "Internal Server Error"); hdr_nocache(); end_headers(); - - vreportf("fatal: ", err, params); } exit(0); /* we successfully reported a failure ;-) */ } +static int die_webcgi_recursing(void) +{ + return dead++ > 1; +} + static char* getdir(void) { struct strbuf buf = STRBUF_INIT; @@ -569,6 +572,7 @@ int main(int argc, char **argv) git_extract_argv0_path(argv[0]); set_die_routine(die_webcgi); + set_die_is_recursing_routine(die_webcgi_recursing); if (!method) die("No REQUEST_METHOD from server"); |