Java Mailing List Archive

http://www.apache-httpd.com/

Home » modperl.perl »

Re: [mp2] mod_perl closes apache's stdin and/or stdout

Heiko Weber

2010-02-05

Replies: Find Java Web Hosting

Author LoginPost Reply
Dear List-Members,

with interest I found the below thread. Starting in Oct. or Nov. last year I am getting a lot of messages in apaches error_log like:

[Fri Feb  5 11:07:09 2010] -e: Software caused connection abort at ...

And it always happen in a print to STDOUT. I notice that it also happen with smaller scripts (running under mod_perl) with no database connection, i.e. scripts which do the following:

use CGI;
use IO::File;

my $q = CGI->new();
print $q->header() . $q->start_html();

my $fp = IO::File->new('< /somewhere/');
if ($fp) {
  binmode STDOUT;
  while (read($fp, $buffer, 1024)) {
        print $buffer;      # << abort points to here !!!
    }
    $fh->close();
}
print $q->end_html();

So I am really wondering whats going on here. The above file works for years now, has not been touched and the content of the opened files isn't empty. The server is a FreeBSD 7.0, apache apache-2.2.14, prefork MPM, mod_perl2-2.0.4 everything from a current freebsd ports.

I use a perl-startup script for apache:

---snip--snip---
#/usr/bin/perl

use CGI();
CGI->compile(':all');
use DBI;
DBI->install_driver("mysql");
use Carp;
---snap---snap---

which is loaded within httpd.conf with:

<IfModule mod_perl.c>
        PerlWarn        On
        PerlTaintCheck  On
        PerlModule      Apache::DBI
        PerlRequire     /usr/local/etc/apache22/perl-startup.pl

        <Perl>
                use CGI::Carp;
        $SIG{__DIE__} = sub { confess shift };
        $SIG{__WARN__} = \&Carp::cluck;
        </Perl>

        <Files *.pl>
                SetHandler      perl-script
                PerlHandler     ModPerl::Registry
                Options         ExecCGI
                PerlSendHeader  On
        </Files>

</IfModule>

I would appreciate any help or ideas to get rid of the aborts.

Heiko



On Tue, Jan 26, 2010 at 5:20 PM, Jonathan Swartz <swartz@pobox.com> wrote:
This never got a response. Which surprises me, since I think it is a
legitimate and nasty bug.

So is the silence because
1) people don't think it's really a bug
2) people glazed over while reading the description
3) ??

4) Don't understand how widespread or common this issue is, or if you
are the only one seeing it.


Thanks :)
Jon

On Jan 8, 2010, at 6:15 AM, Jonathan Swartz wrote:

(A continuation of:
http://marc.info/?l=apache-modperl&m=117507879929572&w=2
http://marc.info/?l=apache-modperl&m=119072925228529&w=2
)

I've just spent many frustrating days debugging a situation that turned
out to be caused by mod_perl's closing of file descriptor 1 (STDOUT).

Here's the reproducible case I ultimately got it down to. Using mod_perl
2, with a dead-simple configuration and this handler:

 use DBI;
 sub handler {
     my $dbh = DBI->connect( "DBI:mysql:$database", $user, $pass, {
RaiseError => 1 } );
     system('echo "hello"');
     eval { $dbh->do("select 1") };
     print "dbh - " . ( $@ ? "error: $@\n" : "ok" ) . "\n";
     return 0;
 }

This outputs:

 dbh - error: DBD::mysql::db do failed: Lost connection to MySQL server
during query at...

The DBI connection dies because mod_perl closes fd 1 (STDOUT). So the next
open - in this case the remote mysql connection created by DBI - gets fd 1.
The child process created by system() writes innocently to STDOUT, which
goes to our mysql socket, causing havoc.

We can confirm this by inserting this at the beginning of the handler:

 sub handler {
      open(my $fh, ">/dev/null");
      print "fh - " . fileno($fh) . "\n";
      ...

Now this outputs:

 fh - 1
 dbh - ok

The initial open grabs fd 1, which means that DBI gets a different fd, and
the connection doesn't die.

Now this example is contrived, but replace 'echo "hello"' with any
innocuous system() or backtick call that accidentally sends a bit of output
to STDOUT, and you can see how this would cause all kinds of baffling bugs.
In my case, it was originally a call to "sendmail" that intermittently sent
a warning to STDOUT, and thus destroyed our first database connection. It
worked fine in mod_perl 1, but started breaking when we upgraded to mod_perl
2.

Is there really no way to fix this in mod_perl, perhaps by automatically
opening a /dev/null handle as I did above? Other future developers will
surely endure the same hours of frustration I did if it is left alone.

Thanks
Jon



©2008 apache-httpd.com - Jax Systems, LLC, U.S.A.