in reply to Re: Non closing sockets - threads
in thread Non closing sockets - threads

Hello Zentara,

I've tried with debugging statements and you were right, the control never gets to the end.
I've tried with shorter timeout, but there is no difference.

If you or BrowserUk, need, I can route my gprs device to some other IP address and simulate disconnects

Regards, Igor

Replies are listed 'Best First'.
Re^3: Non closing sockets - threads
by zentara (Cardinal) on Dec 15, 2008 at 19:47 UTC
    If you or BrowserUk, need, I can route my gprs device to some other IP address

    No thanks....sounds like work. :-)

    You seem to be isolating the problem, what you need to do now is simplify your example for testing/debugging. Always try to start with the simplest setup, get it working, then add complexity. In your case, just try testing 2 GPS devices, and simplify your thread code (or even remove it and just go with IO::Select), until you see disconnects. Try removing all those If statements, and just have super simple code, like:

    if($lclient->connected){ print "1\n"; } else{ print "not connected\n" }
    Then start building from there. You should be able to turn off your device, and see what happens. Play with simple code until it's working under your control.

    I have a feeling that your GPS devices may not be acting like a regular computer would, and you may need to put some IO::Select code into your thread code, so you can use it's can_read, can_write, and has_exception methods to detect problems in the GPS device. You can setup IO::Select to run on just the single client in each thread, like this untested pseudocode:

    my $sel = new IO::Select(); $sel->add($lclient); if($lclient->connected){ print "connected\n"; print "can read\n" if ($sel->can_read); print "can write\n" if ($sel->can_write); print "has exception\n" if ($sel->has_exception); } else{ print "not connected\n" }

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

      I've done a simple test with windows client and minimum code on server side, as you suggested...

      After the client(windows client, putty ...) connects to the server and then you close the client, also the thread on the server is closed.
      But, if you interrupt the connection between the windows client and the server, after few seconds the client is closed, but thread on the server remains connected.
      Timeout on the server side, was set at 5 sec.

      Regards, Igor

        Have you tried the IO::Select methods in the thread? Do you get any exceptions? The thread should be able to detect that can_write isn't true, or that some exception has been raised. Maybe lower timeout even further, like 1 second.

        I'm not really a human, but I play one on earth Remember How Lucky You Are
        But, if you interrupt the connection between the windows client and the server, after few seconds the client is closed, but thread on the server remains connected.

        This is to be expected.

        Once a TCP connection is open it will remain established at each end until it's closed. If one end simply stops sending packets (including closing its end without sending a 'FIN') the other end will wait pretty much indefinitely. (I have tried this with a server running on Linux and Windows XP -- Perl 5.10.0.)

        In this case, the server thread is sat on the while (<$lclient>) waiting for something that will never happen. To avoid this, you need to arrange some form of time-out. The question then is how to establish whether the client has died, or has simply had nothing to say for a while... This rather depends on how the client works.

        I note that the main thread can detect the death of a client when the same $UnitID reconnects.

        Timeout on the server side, was set at 5 sec.

        I believe the timeout value affects only connect and accept.

        Using "SO_KEEPALIVE" at the server end can help, though its usually 2hrs before this starts to worry about the far end having gone quiet -- and then a further 9 x 75secs before it will finally give up.

        Incidentally, passing file handles between threads is generally tricky. In this case:

        while (1) { my $client = $server->accept() ; if (!defined($client)) { ... can do things when accept() times out ... next ; } ; ... prepare to launch thread ... my $thr = threads->new(\&processit, $client)->detach(); } ;
        the GLOB pointed to by $client is duplicated when the new thread is created, so the thread receives a copy of the file handle and $client pointing at it. At the top of the while loop $client is reset, so the file handle for the previous accepted connection is discarded -- meaning that the thread holds the one remaining copy of its file handle, which is what you want ! There are many ways of failing to reach this happy position. (It's not quite so easy to pass a file handle to a pre-existing thread -- but that's another story.)