From 390457c535b59c0069a87f187dee3cc1b1f5910b Mon Sep 17 00:00:00 2001 From: bel Date: Tue, 25 Aug 2015 22:27:55 +0200 Subject: [PATCH] Redirect stderr of CGI process to error log (Step 1/3) --- src/civetweb.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/civetweb.c b/src/civetweb.c index 170f3f5c..62a240dc 100755 --- a/src/civetweb.c +++ b/src/civetweb.c @@ -2691,6 +2691,7 @@ static pid_t spawn_process(struct mg_connection *conn, char *envp[], int fdin, int fdout, + int fderr, const char *dir) { HANDLE me; @@ -2725,6 +2726,13 @@ static pid_t spawn_process(struct mg_connection *conn, 0, TRUE, DUPLICATE_SAME_ACCESS); + DuplicateHandle(me, + (HANDLE)_get_osfhandle(fderr), + me, + &si.hStdError, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); /* If CGI file is a script, try to read the interpreter line */ interp = conn->ctx->config[CGI_INTERPRETER]; @@ -2804,6 +2812,7 @@ static pid_t spawn_process(struct mg_connection *conn, spawn_cleanup: (void)CloseHandle(si.hStdOutput); + (void)CloseHandle(si.hStdError); (void)CloseHandle(si.hStdInput); if (pi.hThread != NULL) { (void)CloseHandle(pi.hThread); @@ -2920,6 +2929,7 @@ static pid_t spawn_process(struct mg_connection *conn, char *envp[], int fdin, int fdout, + int fderr, const char *dir) { pid_t pid; @@ -2947,11 +2957,16 @@ static pid_t spawn_process(struct mg_connection *conn, } else if (dup2(fdout, 1) == -1) { mg_cry( conn, "%s: dup2(%d, 1): %s", __func__, fdout, strerror(ERRNO)); + } else if (dup2(fderr, 2) == -1) { + mg_cry( + conn, "%s: dup2(%d, 2): %s", __func__, fderr, strerror(ERRNO)); } else { - /* Not redirecting stderr to stdout, to avoid output being littered - * with the error messages. */ + /* Keep stderr and stdout in two different pipes. + * Stdout will be sent back to the client, + * stderr should go into a server error log. */ (void)close(fdin); (void)close(fdout); + (void)close(fderr); /* After exec, all signal handlers are restored to their default * values, with one exception of SIGCHLD. According to @@ -6325,12 +6340,12 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog) char *buf; size_t buflen; int headers_len, data_len, i, truncated; - int fdin[2] = {-1, -1}, fdout[2] = {-1, -1}; + int fdin[2] = {-1, -1}, fdout[2] = {-1, -1}, fderr[2] = {-1, -1}; const char *status, *status_text, *connection_state; char *pbuf, dir[PATH_MAX], *p; struct mg_request_info ri; struct cgi_environment blk; - FILE *in = NULL, *out = NULL; + FILE *in = NULL, *out = NULL, *err = NULL; struct file fout = STRUCT_FILE_INITIALIZER; pid_t pid = (pid_t)-1; @@ -6359,13 +6374,13 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog) p = (char *)prog; } - if (pipe(fdin) != 0 || pipe(fdout) != 0) { + if (pipe(fdin) != 0 || pipe(fdout) != 0 || pipe(fderr) != 0) { send_http_error( conn, 500, "Error: Cannot create CGI pipe: %s", strerror(ERRNO)); goto done; } - pid = spawn_process(conn, p, blk.buf, blk.var, fdin[0], fdout[1], dir); + pid = spawn_process(conn, p, blk.buf, blk.var, fdin[0], fdout[1], fderr[1], dir); if (pid == (pid_t)-1) { send_http_error(conn, 500, @@ -6380,6 +6395,8 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog) set_close_on_exec((SOCKET)fdin[1], conn); set_close_on_exec((SOCKET)fdout[0], conn); set_close_on_exec((SOCKET)fdout[1], conn); + set_close_on_exec((SOCKET)fderr[0], conn); + set_close_on_exec((SOCKET)fderr[1], conn); /* Parent closes only one side of the pipes. * If we don't mark them as closed, close() attempt before @@ -6387,7 +6404,8 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog) * Windows does not like when closed descriptor is closed again. */ (void)close(fdin[0]); (void)close(fdout[1]); - fdin[0] = fdout[1] = -1; + (void)close(fderr[1]); + fdin[0] = fdout[1] = fderr[1] = -1; if ((in = fdopen(fdin[1], "wb")) == NULL) { send_http_error(conn, @@ -6403,9 +6421,17 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog) strerror(ERRNO)); goto done; } - + if ((err = fdopen(fderr[0], "rb")) == NULL) { + send_http_error(conn, + 500, + "Error: CGI can not open fdout\nfopen: %s", + strerror(ERRNO)); + goto done; + } + setbuf(in, NULL); setbuf(out, NULL); + setbuf(err, NULL); fout.fp = out; /* Send POST or PUT data to the CGI process if needed */ @@ -6519,6 +6545,13 @@ done: } else if (fdout[0] != -1) { close(fdout[0]); } + + if (err != NULL) { + fclose(err); + } else if (fderr[0] != -1) { + close(fderr[0]); + } + if (buf != NULL) { mg_free(buf); }