Stephane Chazelas wrote:
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.
That's correct, Stephane. The :Apache perlio layer does not use a socket. It uses $r instead, which is already interfacing an existing non-STD socket. That's why the :Apache perlio layer doesn't take over the just released fd.
There is a problem with using a socket with :Apache perlio layer. If we do so Perl will attempt to use that socket. I suppose it's still possible to work around that, you are more than welcome to change the :Apache perlio layer to dup(2). It can be found in modperl_io_apache.[ch] files. modperl_io.c invokes it via open "<:Apache". You can find the documentation of perlio layers in the perliol manpage.
handle_save = gv_fetchpv(Perl_form(aTHX_ "Apache2::RequestIO::_GEN_%ld",
[...]
+ /* 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.
Yes, do_openn (do_open9 is just a wrapper) is hairy. I spent hours deciphering it. I hope the above explanation makes the issue with lack of dup() clear.
-- _____________________________________________________________ Stas Bekman mailto:suppressed http://stason.org/ http://www.linkedin.com/in/stasbekman http://stasosphere.com/ The "Practical mod_perl" book http://modperlbook.org/ http://stason.org/photos/gallery/ http://healingcloud.com
Mail converted by mhonarc 2.6.15
This archive provided courtesy of JSW4.NET, Internet Hosting Services for Small Business.