You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Ken Parzygnat <kp...@raleigh.ibm.com> on 1998/09/25 18:46:37 UTC

[PATCH] Win32 CGI Zombies

There are several PR's (2876,2884,2910) all related
to when the server starts a CGI, and before the CGI
completes, the server kills his side of the pipes (like when the
user hits the Stop button on the browser) and the started
CGI never terminates.

The problem is that when the pipes are created, both handles to
each pipe are inheritable.  When the CGI is started, it is
inheriting the handles it uses as well as the handles that the server
uses.  Therefore, even though the server closes its handles,
the pipe remains unbroken because the CGI still has valid handles
to both sides.  This leads to the CGI hanging.

To ensure that this does not happen, we must not allow the server
side handles to be inherited.  In PR 2884, a user (Mike Sample)
supplied some code to fix this problem.  In the supplied code, Mike
uses SetHandleInformation to make the handles not inheritable.  This
code worked when I tried it on NT.  However, the Microsoft Developer's
Network suggests that you should use DuplicateHandle to make the
handle not inheritable.  Additionally, the MSDN says that
SetHandleInformation is not supported on Win95, while DuplicateHandle
is.  Therefore, to be better safe than sorry, I reworked the fix using
DuplicateHandle.

Let me know what you think!


--- alloc.c.orig	Wed Sep 23 20:53:16 1998
+++ alloc.c	Thu Sep 24 11:52:59 1998
@@ -2280,6 +2280,10 @@
     HANDLE hPipeInputWrite  = NULL;
     HANDLE hPipeErrorRead   = NULL;
     HANDLE hPipeErrorWrite  = NULL;
+    HANDLE hPipeInputWriteDup = NULL;
+    HANDLE hPipeOutputReadDup = NULL;
+    HANDLE hPipeErrorReadDup  = NULL;
+    HANDLE hCurrentProcess;
     int pid = 0;
     child_info info;

@@ -2317,6 +2321,58 @@
 	    CloseHandle(hPipeOutputWrite);
 	}
 	return 0;
+    }
+
+    /*
+     * When the pipe handles are created, the security descriptor
+     * indicates that the handle can be inherited.  However, we do not
+     * want the server side handles to the pipe to be inherited by the
+     * child CGI process. If the child CGI does inherit the server
+     * side handles, then the child may be left around if the server
+     * closes its handles (e.g. if the http connection is aborted),
+     * because the child will have a valid copy of handles to both
+     * sides of the pipes, and no I/O error will occur.  Microsoft
+     * recommends using DuplicateHandle to turn off the inherit bit
+     * under NT and Win95.
+     */
+    hCurrentProcess = GetCurrentProcess();
+    if ((pipe_in &&
+        !DuplicateHandle(hCurrentProcess, hPipeInputWrite, hCurrentProcess,
+            &hPipeInputWriteDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) ||
+        (pipe_out &&
+        !DuplicateHandle(hCurrentProcess, hPipeOutputRead, hCurrentProcess,
+            &hPipeOutputReadDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) ||
+        (pipe_err &&
+        !DuplicateHandle(hCurrentProcess, hPipeErrorRead, hCurrentProcess,
+            &hPipeErrorReadDup, 0, FALSE, DUPLICATE_SAME_ACCESS))) {
+
+        if(pipe_in) {
+            CloseHandle(hPipeInputRead);
+            CloseHandle(hPipeInputWrite);
+        }
+        if(pipe_out) {
+            CloseHandle(hPipeOutputRead);
+            CloseHandle(hPipeOutputWrite);
+        }
+        if(pipe_err) {
+            CloseHandle(hPipeErrorRead);
+            CloseHandle(hPipeErrorWrite);
+        }
+        return 0;
+    }
+    else {
+        if (pipe_in) {
+            CloseHandle(hPipeInputWrite);
+            hPipeInputWrite = hPipeInputWriteDup;
+        }
+        if (pipe_out) {
+            CloseHandle(hPipeOutputRead);
+            hPipeOutputRead = hPipeOutputReadDup;
+        }
+        if (pipe_err) {
+            CloseHandle(hPipeErrorRead);
+            hPipeErrorRead = hPipeErrorReadDup;
+        }
     }

     /* The script writes stdout to this pipe handle */


- - - - - - - - - - - - - - - - - -
Ken Parzygnat
email: kparz@raleigh.ibm.com


----------------------------------------------------------------------------
----
Users of the Apache webserver are hereby granted a non-exclusive,
irrevocable,
world-wide, royalty-free, non-transferable license to use, execute, prepare
derivative works of, and distribute (internally and externally, and
including
derivative works) the code accompanying this license as part of, and
integrated into the Apache webserver.  This code is provided "AS IS" WITHOUT
WARRANTY OF ANY KIND EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTY OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
AND ANY WARRANTY OF NON-INFRINGEMENT.  THE ENTIRE RISK ARISING OUT OF THE
USE
OR PERFORMANCE OF THIS CODE REMAINS WITH USERS OF THE APACHE WEBSERVER.  The
owner of this code represents and warrants that it is legally entitled to
grant the above license.