suaveant has asked for the wisdom of the Perl Monks concerning the following question:

Ok... so we use FCGI, and I hate it, since when we have problems I can't track them down. SO... I am writing a perl version. Not that that is terribly important.

What is important is that I have a server process, which manages multiple children listening to the same socket. To keep track of these children and decide if I need to fork more or reap a few, I have two way pipes that talk to a master process, saying when they get a call and when they are done with a call.

My problem is that I have all the child read pipes in IO::Select, and occasionally (easy to duplicate if the waiting message quickly follows the call message) I lose the waiting message. Basically I have one line messages, so can_read returns, I get the 'call' message, then I return. The 'waiting' message may already be there, but I leave that for the next cycle for can_read to pick up again. However, it doesn't always get picked up.

Any ideas? Am I going about this the wrong way? I tested and found the 'waiting' message was actually there. I had assumed that if I didn't read everything from the socket that can_read would return true until there was nothing left to read... am I wrong. Or am I possibly not using the proper read method? Maybe perl is doing some weird buffering when I use $msg = scalar <$cr>; ?

Of course, if anyone has suggestions on how better to track when the children are in a call I'm open to that, too... I don't know if there is any way to tell how many children are listening on a socket or something similar.

Below is a snippet of the code:

for(0..1) { my @ready = $self->{root}{select}->can_read(0); for(@ready) { $self->handle_child_message($self->{root}{childreads}{$_},$_); } } sub handle_child_message { my $self = shift; my $child = shift; my $cr = shift; my $msg = <$cr>; if($msg =~ /^call/) { $self->{root}{busy}{$child} = 1; $self->{root}{busycount}++; $self->{root}{children}{$child}{calls}++; } elsif($msg =~ /^waiting/) { $self->{root}{busycount}-- if delete $self->{root}{busy}{$chil +d}; } }

                - Ant
                - Some of my best work - (1 2 3)

Replies are listed 'Best First'.
•Re: IO::Select can_read missing some reads...
by merlyn (Sage) on Mar 13, 2002 at 16:57 UTC
    Rule #1 with I/O: don't mix buffered operations (read, readline/<HANDLE>, seek, print) with unbuffered operations (select, sysread, sysseek, syswrite). You broke rule #1.

    Change your readline op to a sysread, and you'll probably have much better functionality, or reveal a bug somewhere else instead. {grin}

    -- Randal L. Schwartz, Perl hacker

      Ahhh ues.. I actually had a thought about buffering as I was writing the question... sysread does fix the problem nicely, it would seem... thanks! :)

                      - Ant
                      - Some of my best work - (1 2 3)

Re: IO::Select can_read missing some reads...
by jeffenstein (Hermit) on Mar 13, 2002 at 18:32 UTC

    Ok, so this isn't strictly an answer to your question, as merlyn seems to have done that, but...

    Did you know that you can start static fcgi applications with cgi-fcgi? (Comes with mod_fcgi.) You'll just have to give a server and port in the apache config file to point to your app. This lets you start it on a tty and see any startup errors.

    You can also point your stderr anywhere you want after the script starts with open STDERR, ">>logfile"; select( (select(STDERR), $|=1)[0]);. This also sets stderr to unbuffered output, but may be superfluous. It might also be helpful to do this after the accept, then close at the end of the loop, so you can move aside large log files.

    It's very helpful for daemons / cgi to log everything. This will help to pinpoint problems, and disk space is usually cheaper than programmer time.

      Well... you can also run a fastcgi on the command line... which we do... the problems I refer to are involved more with things like problesm with STDOUT and a strange problem where cgi-fcgi is having problems with our firewall... and packets are getting mangled... I looked at the cgi-fcgi c code... and it was awful...

      End result, it is easier to rewrite FCGI in perl, which also gives us the added bonus of changing the number of availble fastcgi clients on demand, and graceful shutdowns, so they act more like apache... very nice... seems to be coming together nicely...

                      - Ant
                      - Some of my best work - (1 2 3)

Re: IO::Select can_read missing some reads...
by Rex(Wrecks) (Curate) on Mar 13, 2002 at 18:33 UTC
    There is also some very good examples and explinations revolving around this in Network Programming with Perl. Chapter 12 goes into detail about IO::Select.

    I highly recommend picking this up!

    "Nothing is sure but death and taxes" I say combine the two and its death to all taxes!