On Mon, Apr 02, 2007 at 03:52:50PM -0700, Stas Bekman wrote: > Stephane, you are correct in your observations that original STDIN and > STDOUT filehandles are not preserved when perlio CGI mode is used. > > This is because how Perl works. Consider the following perl program, run from > the command line (not mod_perl!): >
Hi Stas, that's not what I think happens though. I suspected as well that the responsible code was in src/modules/perl/modperl_io.c And it does IIUC: open STDIN_SAVED, "<&STDIN" or die "Can't dup STDIN: $!"; close STDIN; open STDIN, "<:apache" and same for STDOUT. And it should work, except that the second open, which should resolve to a dup2 or dup system call doesn't seem to do anything file-descriptor-wise. It rather looks like is assignes the STDIN perl handle to the Socket, so that STDIN no longer has the fd 0 (as demonstrated by my test of executing a lsof command within a CGI script), but something more like 16, which was returned by the accept() of the incoming HTTP connection. [...] > + fprintf(stderr, "STDIN orig: %d\n", > + (int)PerlIO_fileno(IoIFP(GvIOn(handle)))); > + > MP_TRACE_o(MP_FUNC, "start"); > > /* if STDIN is open, dup it, to be restored at the end of response */ > if (handle && SvTYPE(handle) == SVt_PVGV && > IoTYPE(GvIO(handle)) != IoTYPE_CLOSED) { > + > handle_save = gv_fetchpv(Perl_form(aTHX_ > "Apache2::RequestIO::_GEN_%ld", > (long)PL_gensym++), > @@ -132,6 +138,21 @@ > * have file descriptors, so STDIN must be closed before it can > * be reopened */ > do_close(handle, TRUE); > + > + /* now grab the just released fd, normally 0 */ > + handle_save_fd = gv_fetchpv("GENX2", TRUE, SVt_PVIO); > + > + /* open my $oldout, "<&=0" or die "Can't save STDIN's fd: $!"; */ > + status = do_open(handle_save_fd, "</dev/null", 10, FALSE, > + O_RDONLY, 0, Nullfp); [...] You don't want that IMO, you want the fd 0 and 1 to point to the socket so that the CGI has both its stdin and stdout pointing to the socket, because that's how unmodified CGI scripts do. system("echo foo"); Should output "foo\n" to the page returned by the CGI. and echo foo does a write(1, "foo\n", 4); I must confess I tried to follow in the perl code what that do_open9 call that was supposed to dup the socket into stdin/stdout was doing but didn't get very far. I tried to replace those perl functions to real close() and dup()s but it didn't help either. -- Stephane