>>>>> "RS" == Russell Steinthal <rms39@columbia.edu> writes:
RS> We're probably nearing the limits of my socket programming knowledge,
No problem; I just expanded mine a bit. The moral: when the Camel says not
to mix select and buffered reads unless you really know what you're doing,
and you don't really know what you're doing, you should heed the warning.
The problem is, of course, that the getline call reads a lot more than one
line and stuffs the rest in a buffer somewhere. Then the next select call
comes up and it fails because there's nothing left to read from the socket.
It's all in the buffer...
Thankfully everything's OO down there, so I can make one localized change
and everything else should fall into place.
Please try this patch on for size:
Index: lib/Mj/Deliver/Connection.pm
--- Connection.pm 1998/03/27 04:42:00 1.1.1.1
+++ Connection.pm 1998/05/09 06:38:30
@@ -13,6 +13,10 @@
the same interface. An earlier version of this code supported executing a
program with the Connection object encapsulating its input and output.
+This class also encapsulates a simple buffered IO mechanism over unbuffered
+sysread and syswrite. This enables us to use select calls to provide real
+timeouts on socket reads. (The buffered writes are still used, right now.)
+
=cut
package Mj::Deliver::Connection;
@@ -47,6 +51,7 @@
return undef unless $self->{'outhandle'};
$self->{'outhandle'}->autoflush(1);
$self->{'outsel'} = new IO::Select $self->{'outhandle'};
+ $self->{buffer} = '';
return $self;
}
@@ -68,6 +73,10 @@
This grabs a line from the connection, timing out (and returning undef)
appropriately.
+Because select and getline (and buffered input in general) don''t mix, we
+maintain our own buffer and read a chunk off of the socket whenever it is
+necessary.
+
There was support for a separate input handle, but the support for
communicating with a pair of filehandles has been scrapped. (That was the
original reason for this module, but...)
@@ -75,8 +84,16 @@
=cut
sub getline {
my $self = shift;
- return undef unless $self->{'outsel'}->can_read($self->{'timeout'});
- $self->{'outhandle'}->getline;
+ my ($len);
+
+ while(!length($self->{buffer}) || $self->{buffer} !~ /\n/) {
+ return undef unless $self->{outsel}->can_read($self->{timeout});
+ $len = $self->{outhandle}->sysread($self->{buffer}, 1024,
+ length($self->{buffer}));
+ return undef unless $len;
+ }
+ $self->{buffer} =~ s/^([^\n]*\n)//;
+ $1;
}
=head2 fileno
- J<
Follow-Ups:
References:
|
|