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

Esteemed Monks,

I'm currently working on a project that involves listening on a few ports and decoding the incoming packets.

For each port, I created a thread and started the IO::Socket::INET recv() loop. It's working, I can get the info, but I cannot send any messages to these threads with Thread::Queue because of the blocking socket connection I presume.

So using Thread::Queue is meaningless? And, how can I exit properly from these threads?

One small detail friends, the main thread has wxPerl, and the workers feed the main thread with data.

Replies are listed 'Best First'.
Re: IO::Socket::INET in worker threads
by gone2015 (Deacon) on Feb 14, 2009 at 14:28 UTC

    Yes, once a thread has blocked on a recv waiting for something from the far end, you are stuck. With a TCP connection, if the far end simply stops talking to you, recv will wait for a very long time indeed. With UDP there is no connection to close even.

    Thread::Queue has no mechanism for interrupting recv.

    I think the simplest way to tackle this is to implement a time-out on recv. I would recommend using IO::Select for this (see recent thread). Now you can both time-out dead connections and periodically look for messages from the mother-ship.

    If you want the thread to respond instantly to a message from the mother-ship, then you have a rather harder problem. You could replace your Thread::Queue by an intra-machine socket connection (or use such a connection to signal that data is available). Now in your thread you need to use IO::Select on both sockets. This does appear to be overkill ! (I'd have to be very sure that a simple time-out really wasn't acceptable...)

    Sadly, thread signalling does not interrupt I/O operations... so no help from that quarter.

    If all you want to do is to terminate the thread and its connection, you could shutdown the connection.

Re: IO::Socket::INET in worker threads
by zentara (Cardinal) on Feb 14, 2009 at 14:57 UTC
    Without seeing your code, if you keep the threads in a recv() loop, you are effectively locking them into just receiving. 2-way sockets need to be handled in a bi-directional manner, see Simple threaded chat server for some ideas. Else, you can use a shared variable to your threads, which they can use to switch them to the send() mode.

    Or you could spawn 2 threads, one for sending or for receiving. This is what is commonly done in socket clients, they are forked( or threaded) to make them receive/send at the same time....i.e. bidirectional. See Simple bi-directional forking commandline client

    Without the bidirectional forking/threading/select code in your socket code, you will need to setup a protocol to tell both ends of the connection which mode to be in send() or recv(), and constantly juggle them.


    I'm not really a human, but I play one on earth My Petition to the Great Cosmic Conciousness
Re: IO::Socket::INET in worker threads
by weismat (Friar) on Feb 14, 2009 at 06:08 UTC
    I agree with BrowserUK, that it would be nice to have more details.
    Nevertheless I guess you need to try a non-blocking read from Thread::Queue via the dequeue_nb function.
    For non-blocking receive from sockets you may look at recv in socket programming.
      Thanks guys, sorry for not providing enough info, i'm not a networking expert so choosing the right words is difficult.

      weismat, I can maybe ask a better question following your advice.

      How can I implement a non-blocking receive from sockets with threads?

      Also I'm now looking into how I can use select for the same purpose.
Re: IO::Socket::INET in worker threads
by targetsmart (Curate) on Feb 14, 2009 at 06:16 UTC
    When-ever I feel that I can try threads, I can also use fork to solve the same problem with ease; with more control over the process/problem and what is expected to happen
    most of the modules(CPAN/core) just works fantastic with forked processes, I fear whether it would work properly with threads.
    This is my opinion and I am happy working with processes rather than threads.

    Vivek
    -- In accordance with the prarabdha of each, the One whose function it is to ordain makes each to act. What will not happen will never happen, whatever effort one may put forth. And what will happen will not fail to happen, however much one may seek to prevent it. This is certain. The part of wisdom therefore is to stay quiet.
Re: IO::Socket::INET in worker threads
by BrowserUk (Patriarch) on Feb 14, 2009 at 02:18 UTC