Package: speedy-cgi-perl
Version: 2.22-1
Tags: patch,upstream
Severity: normal
Hi,
I have already reported this in the
upstream bugzilla as SourceForge bug 1279867,
http://sourceforge.net/tracker/index.php?func=detail&aid=1279867&group_id=2208&atid=102208
but since it seems pretty quiet there (no bug or CVS activity for almost
two years), I'm sending it here as well.
I'd be glad if somebody could try to reproduce the bug and see if
the patch helps. I'm not a C wizard, and there might well be a better
fix. Anyhow, the bug affects Smokeping development and I'd like to see
it fixed.
Upstream bug report follows:
-----------------------------
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 [EMAIL PROTECTED]
--- src/speedy_main.c 2005/08/31 19:56:57 1.1
+++ src/speedy_main.c 2005/08/31 19:57:42
@@ -299,6 +299,7 @@
/* Copy streams */
while (1) {
/* Do reads/writes */
+ int close_stdout_delayed = 0;
for (i = 0; i < NUMFDS; ++i) {
register CopyBuf *b = cb + i;
int do_read = my_canread(b) &&
@@ -346,10 +347,17 @@
/* Try to close files now, so we can wake up the backend
* and do more I/O before dropping into select
*/
- if (!do_read && !do_write)
- try_close(b);
- }
- }
+ if (!do_read && !do_write) {
+ if (i == 1)
+ /* delay closing STDOUT until all the other fds are
closed */
+ close_stdout_delayed = 1;
+ else
+ try_close(b);
+ }
+ }
+ }
+ if (close_stdout_delayed)
+ try_close(cb+1);
/* All done with reads/writes after backend exited */
if (backend_exited) {