diff --git a/src/civetweb.c b/src/civetweb.c index eb2ff2f3d..ec6e01b72 100644 --- a/src/civetweb.c +++ b/src/civetweb.c @@ -5848,7 +5848,7 @@ mg_stat(const struct mg_connection *conn, static void -set_close_on_exec(SOCKET fd, +set_close_on_exec(int fd, const struct mg_connection *conn /* may be null */, struct mg_context *ctx /* may be null */) { @@ -5941,17 +5941,16 @@ spawn_process(struct mg_connection *conn, (void)envblk; - if (conn == NULL) { - return 0; - } - if ((pid = fork()) == -1) { /* Parent */ - mg_send_http_error(conn, - 500, - "Error: Creating CGI process\nfork(): %s", - strerror(ERRNO)); - } else if (pid == 0) { + mg_cry_internal(conn, "%s: fork(): %s", __func__, strerror(ERRNO)); + } else if (pid != 0) { + /* Make sure children close parent-side descriptors. + * The caller will close the child-side immediately. */ + set_close_on_exec(fdin[1], conn, NULL); /* stdin write */ + set_close_on_exec(fdout[0], conn, NULL); /* stdout read */ + set_close_on_exec(fderr[0], conn, NULL); /* stderr read */ + } else { /* Child */ if (chdir(dir) != 0) { mg_cry_internal( @@ -11063,14 +11062,6 @@ handle_cgi_request(struct mg_connection *conn, const char *prog) } #endif - /* Make sure child closes all pipe descriptors. It must dup them to 0,1 */ - set_close_on_exec((SOCKET)fdin[0], conn, NULL); /* stdin read */ - set_close_on_exec((SOCKET)fdin[1], conn, NULL); /* stdin write */ - set_close_on_exec((SOCKET)fdout[0], conn, NULL); /* stdout read */ - set_close_on_exec((SOCKET)fdout[1], conn, NULL); /* stdout write */ - set_close_on_exec((SOCKET)fderr[0], conn, NULL); /* stderr read */ - set_close_on_exec((SOCKET)fderr[1], conn, NULL); /* stderr write */ - /* Parent closes only one side of the pipes. * If we don't mark them as closed, close() attempt before * return from this function throws an exception on Windows. @@ -11080,41 +11071,17 @@ handle_cgi_request(struct mg_connection *conn, const char *prog) (void)close(fderr[1]); fdin[0] = fdout[1] = fderr[1] = -1; - if ((in = fdopen(fdin[1], "wb")) == NULL) { - status = strerror(ERRNO); - mg_cry_internal(conn, - "Error: CGI program \"%s\": Can not open stdin: %s", - prog, - status); - mg_send_http_error(conn, - 500, - "Error: CGI can not open fdin\nfopen: %s", - status); - goto done; - } - - if ((out = fdopen(fdout[0], "rb")) == NULL) { + if (((in = fdopen(fdin[1], "wb")) == NULL) + || ((out = fdopen(fdout[0], "rb")) == NULL) + || ((err = fdopen(fderr[0], "rb")) == NULL)) { status = strerror(ERRNO); mg_cry_internal(conn, - "Error: CGI program \"%s\": Can not open stdout: %s", + "Error: CGI program \"%s\": Can not open fd: %s", prog, status); mg_send_http_error(conn, 500, - "Error: CGI can not open fdout\nfopen: %s", - status); - goto done; - } - - if ((err = fdopen(fderr[0], "rb")) == NULL) { - status = strerror(ERRNO); - mg_cry_internal(conn, - "Error: CGI program \"%s\": Can not open stderr: %s", - prog, - status); - mg_send_http_error(conn, - 500, - "Error: CGI can not open fderr\nfopen: %s", + "Error: CGI can not open fd\nfdopen: %s", status); goto done; } @@ -11270,6 +11237,9 @@ handle_cgi_request(struct mg_connection *conn, const char *prog) if (fdout[1] != -1) { close(fdout[1]); } + if (fderr[1] != -1) { + close(fderr[1]); + } if (in != NULL) { fclose(in);