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