The changes in APR 1.2.10+ and Apache 2.2.6 caused mod_perl 2.0.3 to fail on Windows. mod_perl attempts to save stdin and stdout on entry and restore them on exit. mod_perl uses POSIX-like int file descriptors - _fileno(stdin) and _fileno(stdout) - for this. These file descriptors are not updated by setting STD_INPUT_HANDLE and STD_OUTPUT_HANDLE via SetStdHandle(). For example, SetStdHandle(STD_INPUT_HANDLE, newhand) does not change the HANDLE associated with _fileno(stdin). _fileno(stdin) still refers to the original Windows HANDLE - the pipe handle, regardless of whether it is open or has been closed. This can be seen by comparing the return value from GetStdHandle(STD_INPUT_HANDLE) to the value from _get_osfhandle(_fileno(stdin)) before and after mpm_winnt.c replaces the stdin handle. mpm_winnt currently creates a HANDLE to "NUL" as a replacement stdout when Apache is run as a Windows Service. Because a console-device HANDLE is not useable (always returns "invalid handle") when it is inherited by a detached process, this is needed for command-line too. Attached is a patch to mpm_winnt (2.2.x branch) which: 1. Creates the "NUL" stdout in the parent for both service and cmd-line execution, rather than just for service. Only single-process mode (-X) retains the original console-device stdout HANDLE. 2. Uses _dup2() in the child to replace the stdin file descriptor with the stdout file descriptor (i.e. to set stdout to "NUL" except in single-process mode). Note that this has the side-effect of closing the regular Windows HANDLE to the stdin pipe too, so it must be done after the child is done reading from the parent. 3. Sets the Windows HANDLEs (but not the file descriptors) for stdout and stderr to INVALID_HANDLE_VALUE at child_init for FastCGI modules. See APR bug 43329. This would allow current Windows FastCGI modules to work with APR 1.2.10+ without requiring APR_NO_FILE flag changes until a major Apache release, while other non-Apache APR programs could still take advantage of the APR process creation changes. This patch works with mod_fastcgi, mod_fcgid, and mod_perl on Win2k and Vista when built with either VC6 and VS8.
Created attachment 20905 [details] mod_perl and FastCGI patch Allows mod_perl and FastCGI programs to run with Apache 2.2.6 on Windows
Typo in 2. above - I meant: "(i.e. to set stdin to "NUL" except in single-process mode)" Also observed that this patch does not interfere with the new APR behavior re: not leaking unwanted handles. rotatelogs.exe works as expected with APR 1.2.10+.
Created attachment 21264 [details] new patch for 2.2.x branch 12/12/2007 Updated patch for 2.2.x trunk (revision 603073 - Dec 12, 2007). Per Bug 43329 - reverting the apr_proc_create behavior fixes the problem for new processes created by mod_fastcgi or mod_fcgid. STD_OUTPUT_HANDLE and STD_ERROR_HANDLE are now INVALID_HANDLE_VALUE as required. The Apache child process itself must be created with valid stdout and stdin file descriptors (vs. HANDLEs) for modules which use fd's. It is OK for these to be file descriptors to "NUL". This patch always creates the Apache child with "NUL" as stdout, which the child later _dup2's to stdin after all the info has been collected from the parent via the stdin pipe. This leaves the Apache child with acceptable fd's for stdin and stdout to satisfy modules which use fd's instead of HANDLEs (like mod_perl).
I'm reviewing the patch I had already authored (see URL above) which applied to both 2.2.x and 2.0.x branches. I'll then examine that it meets the requirements of the patch Tom has attached to this incident, because I think it covers all the bases but need to confirm. If anyone else active in resolving this bug is interested, the current httpd 2.2.x branch from svn, and the 1.2.12 apr[-util] release (or 1.2.x svn branch) can be used to verify the current behavior before release.
(In reply to comment #4) > I'm reviewing the patch I had already authored (see URL above) which applied > to both 2.2.x and 2.0.x branches. Not sure which "URL above" is meant here. The current revision of the 2.2.x branch (rev 607543 30-Dec-2007), which includes change 607311 to mpm_winnt.c, will run mod_perl only when Apache is started as a Windows service. If Apache is started from the command line, the error when mod_perl is invoked is: Failed to dup STDOUT: Bad file descriptor. [Sun Dec 30 08:18:22 2007] [notice] Parent: child process exited with status 9 -- Restarting. It is a welcome improvement that mod_perl errors (like "Failed to dup") now appear in the error log.
Created attachment 21351 [details] Updated patch for 2.2.7 Updated patch to work with Apache 2.2.7 RC. Only the command-line case needed to be fixed. mpm_winnt already creates a stdout handle to "NUL", but only when started as a Windows Service. This "NUL" handle is acceptable to mod_perl as both stdin and stdout. Since console handles don't inherit - when Apache is started from the command-line mod_perl gets an invalid stdout. This patch changes mpm_winnt to *always* create a "NUL" stdout handle when creating a child process, for both Windows service and command-line startup. Single-process mode (-X) has always worked with mod_perl. There is no process creation, therefore no handle inheritance is involved. Because the original (real) console handles are valid, mod_perl runs correctly.
Troubles with this patch; it doesn't mirror unix behavior (which is actually right in this case) and it introduces a service regression just as the earlier patch I committed introduced a console regression. The unix behavior is that the stdout channel should be fixed at the moment that configure is finished. This ensures any normal emits from perl, etc are seen in the parent by the user. I'm working to track down where that happens, it may be at daemonize() and actually embedded in apr, and I'm looking at a best solution to mirror unix. The regression is that stdio (and stderr and stdin) are third rails in a service that we can't touch before they have been repaired. The existing location of the stdout substitution can't and won't be changed. Thanks for the patch and the thorough explanation on dev@httpd, I'm proceeding with the patch that will resolve this without modifying unix nor services.
Here we go; on Unix, apr_proc_detach(1) causes all of the descriptors to be replaced with the /dev/null handle, and this is precisely the behavior we want. Today on unix this occurs in pre_config (c.f. worker.c and prefork.c). However this behavior is a bit borked in the minds of some developers, who are frustrated with the fact that perl emits that showed up in 1.3 no longer show up in 2.0. But I can agree for now that we have to mirror unix, at least our register_hooks and earlier pre_config hooks will mirror unix. See the revised patch which only modifies normal console-mode operation at; http://svn.apache.org/viewvc?view=rev&revision=609354 review and let me know if this satisfies your test cases, and I'll backport ASAP.
Corrected patch cited (now that I can take it to win32). Sorry the initial backport was actually from unix. http://svn.apache.org/viewvc/httpd/httpd/trunk/server/mpm/winnt/mpm_winnt.c?r1=607677&r2=609366
(In reply to comment #9) r609366 applied to Apache 2.2.7 works as expected. Windows-service, command-line, and single-process (-X) all run mod_perl OK with this change. Command-line startup with no console also works OK - e.g. "START /B httpd.exe" or Apache started via CreateProcess(...DETACHED_PROCESS...).
Backported to both 2.0 and 2.2, I think we can at last tag this FIXED for the forthcoming 2.2.8 and 2.0.63 releases. Thanks for all of your help Tom!
(In reply to comment #11) > Backported to both 2.0 and 2.2, I think we can at last tag this FIXED for the > forthcoming 2.2.8 and 2.0.63 releases. Thanks for all of your help Tom! Thanks for the kind words - but you may not want to thank me just yet. I failed to notice that with the current fix, closing the Apache window does not shut down Apache (presuming a window is displayed) . Ditto for right-click [Close] on the task-bar icon. This was not a problem with the previous patch, so somehow the windows console (vs. the child window itself) is not associated with the parent process with this fix. I see this on Win2k and Steffen reports the same on XP. I regret we didn't catch this quicker.
Fixed in 2.2.8.