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

Monks! I throw myself at your infinite wisdom and mercy, to end my suffering! For about a week now I've been fighting with this small bit of code, reading anything I can find about it, and am certain it's something really simple/obvious I'm missing. This piece of code here, which I've assembled from examples from here, books, etc, works wonderfully for a threaded tcp server reading data. However, when a timeout occurs the while loop just continues forever. I know there should be a "connection reset by peer" or some error popping up, but nothing does, and thusly the thread never dies. Spare my poor lungs, they can't take anymore furious chainsmoking while yelling at the screen!
vec($rin,fileno($self),1) = 1; vec($ein,fileno($self),1) = 1; vec($win,fileno($self),1) = 1; while(1) { ($found) = select($rout=$rin,$wout=$win,$eout=$ein,1); if($found) { my $rc = sysread($in,$buf,1024); if(defined $rc) { # non-error if ($rc > 0) { # read successful print "Got $buf\n"; runplayer($self,$buf,$out); } else { # end of file print "EOF\n"; last; } } else { print "sysread() error: $!\n"; last; } } }

Replies are listed 'Best First'.
Re: Threaded sockets, etc.
by shmem (Chancellor) on Aug 29, 2008 at 18:30 UTC

    Why do you expect the error being in the code you posted?

    Q: Hey, what are you doing here at the lantern?
    A: Lost my keys, searching.
    Q: Where did you loose them?
    A: Over there, in the dark.
    Q: Then why are you searching here?
    A: 'cause it's bright here.

    Post surrounding code. The dark stuff: threading sockets...

      Oh I forgot to mention that when it's not a timeout, when it's a proper disconnect, everything works fine and gets EOF and exits properly, the thread dies properly, etc. Basically it's just
      while(1) { while (my $connection = $main->accept) { threads->create(\&initplayer,$connection); }
      then
      sub initplayer { my $hand = shift; $hand->blocking(0); print "INITPLAYER CALLED!\n"; threads->detach; doplayer($hand,$hand,$hand); remove_player($hand); print "THREAD DESTROYED!\n"; $hand->close(); }
      and doplayer contains the code I posted before. I added a print line inside the while loop and it continues to print after the timeout, so it's not a blocking issue.
Re: Threaded sockets, etc.
by apl (Monsignor) on Aug 29, 2008 at 19:11 UTC
    When I timeout, I disconnect and reconnect before I try doing another select. Most of the protocols I use involve heartbeats, so if I haven't received a response in a certain amount of time, it generally means there's a problem with the other side.

    You might want to try the same.
Re: Threaded sockets, etc.
by Illuminatus (Curate) on Aug 29, 2008 at 18:49 UTC
    How do you know a timeout is occurring? I have a few questions:
    1) I assume that $in really is the fileno for $self.
    2) You do realize that you are setting both the read *and* write bits for $self/$in? This means that the select will return $found>0 if $self/$in is writable but not readable. This will cause the sysread to hang. Is that what you expect?
      Basically I have a test client which connects fine, disconnects fine, but if I leave it alone for a while loses the connection to the server, but the server continues that while loop. I suppose you could say I'm assuming a timeout occurs, or at least some problem that only shows itself when there is no activity for a period of time. (If the client is sporadically sending information, the problem does not rear its ugly head! 1. Correct. 2. That last addition (adding the write bit) was me hoping that it'd return something useful/not getting it, the problem was there before that change. More to the point, and a terrible thing to do, but I added the select call later in an attempt to fix the problem, at first it was just sysreading in a while loop, and then ignoring "resource temporarily not available" errors. Even then, sysread wouldn't return EOF when the client was left idling for a while.
Re: Threaded sockets, etc.
by eosbuddy (Scribe) on Aug 30, 2008 at 12:00 UTC
    You could set an alarm(200) and break away from the infinite while loop; changing the 200 secs to whatever you think fit for a timeout?
Re: Threaded sockets, etc.
by zentara (Cardinal) on Aug 31, 2008 at 13:04 UTC
    You didn't post all the code needed to debug, so we guess.

    while loop just continues forever.

    Usually when I see complain about this in threaded apps, it involves the threads never returning( ending ). You might want to look at Simple threaded chat server . Look at the if($client->connected)....or else close $client. Depending on your code, you might also look at the $select->can_read and $select->can_write methods, and put them in an if-block.


    I'm not really a human, but I play one on earth Remember How Lucky You Are