HTTP::Daemon and 'broken pipe' errors

jjohn on 2002-11-20T03:47:55

I'm working on a game similar to Funeral Quest (an upgrade to which is due soon). It's a turned-based web game based on UFOlogy (go with what you know, I say). I'll have details on the game some. Naturally, the game is written in Perl.

The game includes a single-threaded web server implemented with Gisle Aas' HTTP::Daemon Class. It's single-threaded because I want to allow users to run the server on Winders, should they choose to and I couldn't figure out how to use threads or ithreads (am I supposed to have access to ithreads?) on win32.

For simple tests, getting a file or a small web page, HTTP::Daemon works fine. The problem started when it attempted to serve a web page with 15 images on it. When the server tried to server the third file (an image), I'd get a 'broken pipe' error my server would halt. As I worked to isolate the problem, I found that the error was coming from this simple loop in HTTP::Daemon::ClientConn::send_file:

    while ($n = sysread($file, $buf, 8*1024)) {
        last if !$n;
        $cnt += $n;
	print $self $buf;
    }

As I step through this code in the debugger, I found that after the second iteration $self (a kind of IO::Socket::INET object) would choke. Bummer. I tried changing from print to syswrite, but that didn't change the behavoir at all.

I turned to Google.

Digging around, I found this post from 1997:

Gisle Aas (gisle@aas.no)
26 Nov 1997 11:39:19 +0100 

Previous message: Gisle Aas: "Re: libwww-per-5.16" 
In reply to: Joerg Kammerer: "Broken Pipe" 

------------------------------------------------------------------

Joerg Kammerer  writes:

> Hope for a Tip...

Add:

   $SIG{'PIPE'} = 'IGNORE';

to your script.

Sure enough, that seems to do the trick. An early hack I thought of that sort of worked was:

$SIG{WARN} = sub { exec "/usr/bin/perl $0" };

This restarts the server on a broken PIPE error. Unfortunately, the file that choke the server wouldn't get sent.

It would be super if Gisle added this little gotcha to his HTTP::Daemon man page. If not, I'm sure others will find this journal page when they Google for a solution, as I did.

Guru advice is welcomed. Any thoughts on why the server connection chokes? It looks like some kind of I/O buffer is getting full. Because I can safely ignore the signal, I'm guessing that the I/O that trigger the signal gets cleared and more traffic is accepted on that socket. Is this some kind of race condition?

Also, should I abandon the fantasy of expecting perl 5.6.1 threading to work reliably on both Linux and Windows?

You guys are the best...


Perl 5.6.1 threading

samtregar on 2002-11-20T06:34:28

Yes. Immediately abandon the fantasy of getting 5.6.1 threads stable anywhere. Perl's threading support isn't even close to stable until 5.8.0, and even then there are a few problems left to deal with. I wrote an article about threading in Perl that you might find useful.

As for the problems you're having with HTTP::Daemon... Have you considered posting this as a question on PerlMonks? If there's a better answer out there, surely the monks know it.

-sam

Threads in 5.6 are bad, Win32 5.8 has ithreads

sky on 2002-11-20T08:27:00

5005 threads and ithreads in 5.6 are just broken, to get atleast working threads you need 5.8 with ithreads.

I would bet that most win32 6.8 users have ithread enable, the default makefile enables them, and so does ActiveState to allow for psuedo-fork to work.

Re:Threads in 5.6 are bad, Win32 5.8 has ithreads

jjohn on 2002-11-20T14:44:45

Although AS Perl does have a kind of fork(), I understand that process creation is very slow on Win32. That Threading isn't really happening on 5.6.1 makes me feel less stupid for not getting it to work right. ;-)