|
@@ -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 @@ done:
|
|
|
if (fdout[1] != -1) {
|
|
|
close(fdout[1]);
|
|
|
}
|
|
|
+ if (fderr[1] != -1) {
|
|
|
+ close(fderr[1]);
|
|
|
+ }
|
|
|
|
|
|
if (in != NULL) {
|
|
|
fclose(in);
|