On Fri, Jan 08, 2010 at 02:03:00PM -0800, Jonathan Swartz wrote:
> Yup. It seems to be a known behavior in mod_perl:
>
> http://marc.info/?t=117507891100004&r=1&w=2
>
> To me, it seems like a bug, or at least very antisocial behavior (in
> a Unix sense). But remains to be seen what will be done about it.
>
> In the meantime, my workaround is to immediately open a filehandle
> at the beginning of each child process, to use up the STDOUT
> descriptor before DBI does. This seems fragile as it depends on
> open() giving me the next available file descriptor, but I don't
> know what else to do.
It's not fragile as open() is defined to do just that.
> Thanks for your help in pinpointing this.
I'm glad I was able to help.
Tim.
> Jon
>
> On Jan 8, 2010, at 1:43 PM, Tim Bunce wrote:
>
> >On Thu, Jan 07, 2010 at 03:36:21PM -0800, Jonathan Swartz wrote:
> >>
> >>So, is this a bug in DBI, or in the code that closes STDOUT (I'm
> >>assuming that's mod_perl in my original example)?
> >
> >In the code that closes STDOUT. Using truss/strace/dtrace etc
> >to look for close(1) should help pinpoint the code.
> >
> >Tim.
> >
> >>Jon
> >>
> >>On Jan 7, 2010, at 2:57 PM, Martin J. Evans wrote:
> >>
> >>>Jonathan Swartz wrote:
> >>>>Something in which code is closing STDOUT? I know that mod_perl
> >>>>redirects STDOUT to $r->print...
> >>>>
> >>>>Incidentally the code to reprodce for mysql is even easier -
> >>>>just need one connection. This will do it:
> >>>>
> >>>>use DBI;
> >>>>sub handler {
> >>>> my $dbh = DBI->connect( "DBI:mysql:$database", $user,
> >>>>$pass, { RaiseError => 1 } );
> >>>> system(qq{perl -e 'print "abcd"'});
> >>>> eval { $dbh->do("select 1") };
> >>>> print "dbh - " . ( $@ ? "error: $@" : "ok" ) . "\n";
> >>>> return 0;
> >>>>}
> >>>>
> >>>>And as a bonus mystery, if you only print two characters, the
> >>>>request hangs. :)
> >>>>
> >>>>Jon
> >>>>
> >>>This latter fact backs up Tim's conclusion (that is that FD 2 is
> >>>now connected to sybase) even more since the sybase server is
> >>>probably waiting to read more than 2 characters/bytes and so is
> >>>stuck in a loop waiting for more to be sent from the client end.
> >>>
> >>>Martin
> >>>>On Jan 7, 2010, at 2:03 PM, Tim Bunce wrote:
> >>>>
> >>>>>Ah. I think something in the code is closing STDOUT (fd 1)
> >>>>>before the
> >>>>>handler() is called. The socket that the driver then creates
> >>>>>to connect
> >>>>>to the server will get fd 2, aka STDOUT, and thus be inherited
> >>>>>by the
> >>>>>child. Or something like that.
> >>>>>
> >>>>>Tim.
> >>>>>
> >>>>>On Thu, Jan 07, 2010 at 10:03:06AM -0800, Jonathan Swartz wrote:
> >>>>>>Ok, take sendmail out of the equation. The bug will occur iff the
> >>>>>>program sends output to STDOUT (which sendmail was doing
> >>>>>>because of
> >>>>>>a warning).
> >>>>>>
> >>>>>>Here's a slightly simplified version.
> >>>>>>
> >>>>>>our ($dbh1, $dbh2);
> >>>>>>
> >>>>>>sub dbconnect {
> >>>>>> return DBI->connect( 'DBI:Sybase:...', '...', '...', {
> >>>>>>RaiseError => 1 } );
> >>>>>>}
> >>>>>>
> >>>>>>sub testdb {
> >>>>>> my ( $name, $dbh ) = @_;
> >>>>>> eval { $dbh->do("select 1") };
> >>>>>> print "$name - " . ($@ ? "error: $@" : "ok") . "\n";
> >>>>>>}
> >>>>>>
> >>>>>>sub handler {
> >>>>>> my ($r) = @_;
> >>>>>>
> >>>>>> # connect.pl contains one line: BEGIN { $Handler::dbh1 =
> >>>>>>Handler::dbconnect() }
> >>>>>> do "/home/jswartz/projects/unchained-transaction/connect.pl";
> >>>>>> $dbh2 = dbconnect();
> >>>>>> system(qq{perl -e 'print "hi"'});
> >>>>>> testdb("dbh1", $dbh1);
> >>>>>> testdb("dbh2", $dbh2);
> >>>>>>
> >>>>>> return 0;
> >>>>>>}
> >>>>>>
> >>>>>>This outputs
> >>>>>>
> >>>>>>dbh1 - ok
> >>>>>>dbh2 - error: DBD::Sybase::db do failed: OpenClient message:
> >>>>>>LAYER = (5) ORIGIN = (3) SEVERITY = (5) NUMBER = (6)
> >>>>>>Server SANDBOX5, database
> >>>>>>Message String: ct_results(): network packet layer: internal net
> >>>>>>library error: Net-Library operation terminated due to disco\
> >>>>>>nnect
> >>>>>>OpenClient message: LAYER = (1) ORIGIN = (1) SEVERITY = (1)
> >>>>>>NUMBER = (50)
> >>>>>>Server SANDBOX5, database
> >>>>>>Message String: ct_cmd_drop(): user api layer: external error:
> >>>>>>The connection has been marked dead.
> >>>>>>
> >>>>>>However, if I replace the system with
> >>>>>>
> >>>>>>system(qq{perl -e ''});
> >>>>>>or
> >>>>>>system(qq{perl -e 'print "hi"' > /dev/null});
> >>>>>>
> >>>>>>then it outputs
> >>>>>>
> >>>>>>dbh1 - ok
> >>>>>>dbh2 - ok
> >>>>>>
> >>>>>>On Jan 7, 2010, at 2:20 AM, Tim Bunce wrote:
> >>>>>>
> >>>>>>>On Wed, Jan 06, 2010 at 04:08:17PM -0800, Jonathan Swartz wrote:
> >>>>>>>>Thanks for your help...this bug has me feeling very isolated...
> >>>>>>>>
> >>>>>>>>>>Just about everything here is necessary to
> >>>>>>>>>>generate the bug. In
> >>>>>>>>>>particular, I cannot generate the bug...
> >>>>>>>>>>* If I move the code from connect.pl into the
> >>>>>>>>>>handler, even as a
> >>>>>>>>>>string eval
> >>>>>>>>>>* If I remove the "BEGIN" from connect.pl
> >>>>>>>>>>* If I replace sendmail with another program
> >>>>>>>>>
> >>>>>>>>>That's the most interesting one to me. Try replacing
> >>>>>>>>>it with a perl
> >>>>>>>>>script that reports what open file descriptors have
> >>>>>>>>>been inherited.
> >>>>>>>>
> >>>>>>>>Ok. What's the easiest way to do that? :) Sorry, probably dumb
> >>>>>>>>question, but never did this before and scanning perlipc and
> >>>>>>>>perlopentut and google didn't yield anything obvious.
> >>>>>>>
> >>>>>>>I had to rummage around a bit, but this seems to work:
> >>>>>>>
> >>>>>>>$ perl -e 'open(FH, ">&=$_") and printf "$_\n" for 0..100'
> >>>>>>>0
> >>>>>>>1
> >>>>>>>2
> >>>>>>>
> >>>>>>>$ perl -e 'open(FH, ">&=$_") and printf "$_\n" for 0..100' 42<&1
> >>>>>>>0
> >>>>>>>1
> >>>>>>>2
> >>>>>>>42
> >>>>>>>
> >>>>>>>(Using >&= or <&= doesn't seem to matter for this simple case.)
> >>>>>>>
> >>>>>>>Tim.
> >>>>>>
> >>>>
> >>>>
> >>>
> >>
>