Detect remote disconnect in Perl XMPP reader
authorBill Erickson <berick@esilibrary.com>
Mon, 20 Feb 2012 19:40:30 +0000 (14:40 -0500)
committerDan Scott <dan@coffeecode.net>
Mon, 12 Mar 2012 15:40:50 +0000 (11:40 -0400)
When the jabber server severs the connection, it leaves the Perl libs
with a socket that perpetually appears ready for reading, but always
returns 0 bytes.  This produces a loop in the client code.  This change
detects this situation, logs an error, and throws an exception.

Signed-off-by: Bill Erickson <berick@esilibrary.com>
Signed-off-by: Dan Scott <dscott@laurentian.ca>
src/perl/lib/OpenSRF/Transport/SlimJabber/XMPPReader.pm

index 556f597..b8a5da1 100644 (file)
@@ -5,6 +5,7 @@ use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
 use Time::HiRes qw/time/;
 use OpenSRF::Transport::SlimJabber::XMPPMessage;
 use OpenSRF::Utils::Logger qw/$logger/;
+use OpenSRF::EX;
 
 # -----------------------------------------------------------
 # Connect, disconnect, and authentication messsage templates
@@ -211,15 +212,25 @@ sub wait {
     my $buf;
     my $read_size = 1024;
     my $nonblock = 0;
+    my $nbytes;
+    my $first_read = 1;
 
-    while(my $n = sysread($socket, $buf, $read_size)) {
+    while($nbytes = sysread($socket, $buf, $read_size)) {
         $self->{parser}->parse_more($buf) if $buf;
-        if($n < $read_size or $self->peek_msg) {
+        if($nbytes < $read_size or $self->peek_msg) {
             set_block($socket) if $nonblock;
             last;
         }
         set_nonblock($socket) unless $nonblock;
         $nonblock = 1;
+        $first_read = 0;
+    }
+
+    if ($nbytes == 0 and $first_read) {
+        # if the first read on an active socket is 0 bytes, 
+        # the socket has been disconnected from the remote end. 
+        $logger->error("Disconnected from Jabber server");
+        throw OpenSRF::EX::Jabber("Disconnected from Jabber server");
     }
 
     return $self->next_msg;