Hi,
I think I have run into a race condition in the
communication between the speedy frontend and Apache.
When the perl script running in the backend calls
die(), the error message doesn't always reach the web
server error log.
The problem is 100% reproducible for me with SpeedyCGI
2.22 on Debian Sarge using this CGI script:
-------------------
#!/usr/bin/speedy -w
use strict;
use CGI;
my $q = new CGI;
print $q->header;
print "foo\n";
die("bar\n");
-------------------
When invoked with a browser (Firefox), the first "bar"
always ends up in the error log, but nearly none of
subsequent ones (about 1/10 or thereabouts) from a
reload do.
When using curl from the command line, the behaviour is
similar to Firefox.
When using the 'GET' perl program from the libwww-perl
library, no error messages are lost. The difference
seems to be the 'Connection: close' HTTP header that
libwww-perl sends but Firefox and curl don't.
From studying the strace output of 'apache -X', it
seems that the problem triggers when the speedy
frontend closes its STDOUT (going to Apache). Apache
then reacts by killing the CGI with SIGTERM, and
sometimes this happens before the frontend has had time
to read the error output from the backend and copy it
to its own STDERR.
The STDOUT closing apparently happens in try_close(),
called from around line 350 in src/speedy_main.c. The
copy loop there handles and closes STDOUT before
handling STDERR, which AIUI causes the bug.
I'm attaching a proposed patch, which fixes the
behaviour completely for me. Hope it makes sense. I can
also provide strace outputs if you want, but they are
obviously quite lengthy.
Versions of relevant programs on my system:
- SpeedyCGI: 2.22 (speedy-cgi-perl 2.22-1)
- Apache: 1.3.33 (apache 1.3.33-6)
- Perl: 5.8.4 (perl 5.8.4-8)
(I have also reproduced the problem with the CVS
version of speedy_main.c, containing the 'Frontend was
turning off O_APPEND flag on stdout/stderr' patch, so
it's not the same problem.)
Thanks,
--
Niko Tyni ntyni@iki.fi
Proposed patch