Bug 43534 - mod_perl and FastCGI fails on Windows
Summary: mod_perl and FastCGI fails on Windows
Status: RESOLVED FIXED
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: Core (show other bugs)
Version: 2.2.6
Hardware: Other Windows 2000
: P2 normal with 3 votes (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL: http://svn.apache.org/viewvc/httpd/ht...
Keywords: PatchAvailable
Depends on:
Blocks:
 
Reported: 2007-10-02 04:08 UTC by Tom Donovan
Modified: 2008-01-19 11:49 UTC (History)
0 users



Attachments
mod_perl and FastCGI patch (4.55 KB, patch)
2007-10-02 04:10 UTC, Tom Donovan
Details | Diff
new patch for 2.2.x branch 12/12/2007 (3.42 KB, patch)
2007-12-12 10:57 UTC, Tom Donovan
Details | Diff
Updated patch for 2.2.7 (2.20 KB, patch)
2008-01-06 06:40 UTC, Tom Donovan
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tom Donovan 2007-10-02 04:08:33 UTC
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.
Comment 1 Tom Donovan 2007-10-02 04:10:25 UTC
Created attachment 20905 [details]
mod_perl and FastCGI patch

Allows mod_perl and FastCGI programs to run with Apache 2.2.6 on Windows
Comment 2 Tom Donovan 2007-10-02 05:52:13 UTC
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+.
Comment 3 Tom Donovan 2007-12-12 10:57:55 UTC
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).
Comment 4 William A. Rowe Jr. 2007-12-28 13:00:26 UTC
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.
Comment 5 Tom Donovan 2007-12-30 05:43:27 UTC
(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.
Comment 6 Tom Donovan 2008-01-06 06:40:26 UTC
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.
Comment 7 William A. Rowe Jr. 2008-01-06 09:09:46 UTC
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.

Comment 8 William A. Rowe Jr. 2008-01-06 09:38:44 UTC
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.

Comment 9 William A. Rowe Jr. 2008-01-06 10:37:14 UTC
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
 
Comment 10 Tom Donovan 2008-01-07 06:14:03 UTC
(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...).
Comment 11 William A. Rowe Jr. 2008-01-07 09:39:03 UTC
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!
Comment 12 Tom Donovan 2008-01-07 11:45:46 UTC
(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.
Comment 13 Ruediger Pluem 2008-01-19 11:49:57 UTC
Fixed in 2.2.8.