Skip to content

Commit 7253a02

Browse files
peffgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent fdf96a2 commit 7253a02

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

http-backend.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -500,21 +500,24 @@ static void service_rpc(char *service_name)
500500
strbuf_release(&buf);
501501
}
502502

503+
static int dead;
503504
static NORETURN void die_webcgi(const char *err, va_list params)
504505
{
505-
static int dead;
506+
if (dead <= 1) {
507+
vreportf("fatal: ", err, params);
506508

507-
if (!dead) {
508-
dead = 1;
509509
http_status(500, "Internal Server Error");
510510
hdr_nocache();
511511
end_headers();
512-
513-
vreportf("fatal: ", err, params);
514512
}
515513
exit(0); /* we successfully reported a failure ;-) */
516514
}
517515

516+
static int die_webcgi_recursing(void)
517+
{
518+
return dead++ > 1;
519+
}
520+
518521
static char* getdir(void)
519522
{
520523
struct strbuf buf = STRBUF_INIT;
@@ -569,6 +572,7 @@ int main(int argc, char **argv)
569572

570573
git_extract_argv0_path(argv[0]);
571574
set_die_routine(die_webcgi);
575+
set_die_is_recursing_routine(die_webcgi_recursing);
572576

573577
if (!method)
574578
die("No REQUEST_METHOD from server");

0 commit comments

Comments
 (0)