Dmitry Karasik wrote:
Hello,
In mixed environment of mod_perl and cgi, cgi scripts may choose to not use
mod_perl request interface, and read content of POST requests directly from
STDIN. mod_perl during the initialization process closes file descriptor 0,
and frees it for further reuse in other processes. Therefore, any cgi script
executing after mod_perl is initialized, and in the same process tree, will
have file descriptor 0 closed. The concrete example where this behavior leads
to impossibility of processing POST requests is reported earlier and is located
at
http://marc.info/?l=apache-modperl&m=119062450730646&w=2
The proposed patch fixes the issue, however, not being a perl guts expert, I
would urge someone with a deeper knowledge of perl to look at it first. Chances
are that there exists a mechanism in perl that allows non-destructive
duplication and overloading of perl IO handles.
I am not a perl guts expert either (gozer??), but looking through the
perl source it looks like this idiom is used in a few places. But we
really need a reproducible test case to verify that this is indeed a
problem.
I took a quick swing at putting one together but my mod_perl environment
is a bit screwed up right now. Can you see if it runs on your setup?
And hopefully passes with your change, and fails without? This test may
not work at all :) but if it does and this problem is reproducible then
that improves our chances of getting the fix accepted in some form.
Index: ModPerl-Registry/t/conf/extra.conf.in
===================================================================
--- ModPerl-Registry/t/conf/extra.conf.in (revision 543707)
+++ ModPerl-Registry/t/conf/extra.conf.in (working copy)
@@ -182,6 +182,17 @@
PerlResponseHandler ModPerl::Registry
</Location>
+### test for mixed mod_perl/cgi environment ###
+<Location /stdin_override/mod_perl>
+ SetHandler perl-script
+ PerlResponseHandler ModPerl::Registry
+ PerlOptions +ParseHeaders
+</Location>
+
+<Location /stdin_override/cgi>
+ SetHandler cgi-script
+</Location>
+
### deflate tests ###
<IfModule mod_alias.c>
Alias /registry_bb_deflate/ @ServerRoot@/cgi-bin/
Index: ModPerl-Registry/t/cgi-bin/stdin.pl
===================================================================
--- ModPerl-Registry/t/cgi-bin/stdin.pl (revision 0)
+++ ModPerl-Registry/t/cgi-bin/stdin.pl (revision 0)
@@ -0,0 +1,29 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use CGI qw/:standard/;
+
+print <<END;
+Content-type: text/html
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <body>
+ <form method="post"><input type="submit" name="submit" value="Submit">
+ </form>
+END
+
+if (param()) {
+ my $submit = param('submit');
+ if ($submit) {
+ print "<p>submitted</p>";
+ }
+}
+
+print <<END;
+ </body>
+</html>
+END
+
Index: ModPerl-Registry/t/stdin.t
===================================================================
--- ModPerl-Registry/t/stdin.t (revision 0)
+++ ModPerl-Registry/t/stdin.t (revision 0)
@@ -0,0 +1,24 @@
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest qw(POST);
+
+plan tests => 2, need [qw(CGI)],
+ need_min_module_version CGI => 3.08;
+
+{
+ my $url = "/stdin_override/mod_perl";
+ my $res = POST $url;
+
+ ok t_cmp($res->content,
+ qr{submitted},
+ "form submission ok under mod_perl");
+
+ $url = "/stdin_override/cgi";
+ $res = POST $url;
+ ok t_cmp($res->content,
+ qr{submitted},
+ "stdin reset, form submission ok under cgi");
+}
Cheers,
Dmitry Karasik
--- modperl_io.c.orig 2007-09-25 15:36:02.000000000 +0200
+++ modperl_io.c 2007-09-25 15:35:51.000000000 +0200
@@ -129,6 +129,15 @@
Perl_croak(aTHX_ "Failed to dup STDIN: %" SVf, get_sv("!", TRUE));
}
+ /* In mixed environment of mod_perl and cgi scripts, cgi scripts may read content of
+ * POST requests off STDIN. do_close() calls actual close(0), freeing the descriptor 0
+ * for reuse, and creating havoc for anyone reading from file
descriptor 0.
+ * This hack changes the IO type to IoTYPE_STD, because do_close() does
not call
+ * underlying close() on IO handles of these types, but does free the
associated
+ * resources. */
+ if ( IoIFP(io) && PerlIO_fileno(IoIFP(io)) == 0)
+ IoTYPE(io) = IoTYPE_STD;
+
/* similar to PerlIO::scalar, the PerlIO::Apache layer doesn't
* have file descriptors, so STDIN must be closed before it can
* be reopened */
2. Used Components and their Configuration:
*** mod_perl version 2.000003
*** using
/usr/ports/www/mod_perl2/work/mod_perl-2.0.3/lib/Apache2/BuildConfig.pm
*** Makefile.PL options:
MP_APR_LIB => aprext
MP_APXS => /usr/local/sbin/apxs
MP_COMPAT_1X => 1
MP_GENERATE_XS => 1
MP_LIBNAME => mod_perl
MP_USE_DSO => 1
*** The httpd binary was not found
*** (apr|apu)-config linking info
-L/usr/local/lib -laprutil-1 -lexpat -liconv -L/usr/local/lib
-L/usr/local/lib -lapr-1 -lcrypt -lpthread
*** /usr/local/bin/perl -V
Summary of my perl5 (revision 5 version 8 subversion 8) configuration:
Platform:
osname=freebsd, osvers=6.2-release, archname=i386-freebsd-64int
uname='freebsd freebsd.org 6.2-release freebsd 6.2-release #0: sat oct 14
21:57:31 pdt 2006 [EMAIL PROTECTED]:usrsrcsysmagickernelpath i386 '
config_args='-sde -Dprefix=/usr/local -Darchlib=/usr/local/lib/perl5/5.8.8/mach
-Dprivlib=/usr/local/lib/perl5/5.8.8 -Dman3dir=/usr/local/lib/perl5/5.8.8/perl/man/man3
-Dman1dir=/usr/local/man/man1 -Dsitearch=/usr/local/lib/perl5/site_perl/5.8.8/mach
-Dsitelib=/usr/local/lib/perl5/site_perl/5.8.8 -Dscriptdir=/usr/local/bin
-Dsiteman3dir=/usr/local/lib/perl5/5.8.8/man/man3 -Dsiteman1dir=/usr/local/man/man1
-Ui_malloc -Ui_iconv -Uinstallusrbinperl -Dcc=cc -Duseshrplib
-Dccflags=-DAPPLLIB_EXP="/usr/local/lib/perl5/5.8.8/BSDPAN" -Doptimize=-O2
-fno-strict-aliasing -pipe -Ud_dosuid -Ui_gdbm -Dusethreads=n -Dusemymalloc=y
-Duse64bitint'
hint=recommended, useposix=true, d_sigaction=define
usethreads=undef use5005threads=undef useithreads=undef
usemultiplicity=undef
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=define use64bitall=undef uselongdouble=undef
usemymalloc=y, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-DAPPLLIB_EXP="/usr/local/lib/perl5/5.8.8/BSDPAN"
-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe
-Wdeclaration-after-statement -I/usr/local/include',
optimize='-O2 -fno-strict-aliasing -pipe ',
cppflags='-DAPPLLIB_EXP="/usr/local/lib/perl5/5.8.8/BSDPAN" -DHAS_FPSETMASK
-DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -Wdeclaration-after-statement
-I/usr/local/include'
ccversion='', gccversion='3.4.6 [FreeBSD] 20060305', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
alignbytes=4, prototype=define
Linker and Libraries:
ld='cc', ldflags =' -Wl,-E -L/usr/local/lib'
libpth=/usr/lib /usr/local/lib
libs=-lm -lcrypt -lutil
perllibs=-lm -lcrypt -lutil
libc=, so=so, useshrplib=true, libperl=libperl.so
gnulibc_version=''
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='
-Wl,-R/usr/local/lib/perl5/5.8.8/mach/CORE'
cccdlflags='-DPIC -fPIC', lddlflags='-shared -L/usr/local/lib'
Characteristics of this binary (from libperl):
Compile-time options: MYMALLOC PERL_MALLOC_WRAP USE_64_BIT_INT
USE_LARGE_FILES USE_PERLIO
Locally applied patches:
defined-or
Built under freebsd
Compiled at Oct 15 2006 05:04:59
%ENV:
PERL_LWP_USE_HTTP_10="1"
@INC:
/usr/local/lib/perl5/5.8.8/BSDPAN
/usr/local/lib/perl5/site_perl/5.8.8/mach
/usr/local/lib/perl5/site_perl/5.8.8
/usr/local/lib/perl5/site_perl
/usr/local/lib/perl5/5.8.8/mach
/usr/local/lib/perl5/5.8.8
.
*** Packages of interest status:
Apache2 : -
Apache2::Request : -
CGI : 3.15
ExtUtils::MakeMaker: 6.30, undef
LWP : 5.805
mod_perl : -
mod_perl2 : 2.000003
This report was generated by t/REPORT on Tue Sep 25 13:39:09 2007 GMT.
-------------8<---------- End Bug Report --------------8<----------
Note: Complete the rest of the details and post this bug report to
modperl <at> perl.apache.org. To subscribe to the list send an empty
email to [EMAIL PROTECTED]