|P is for Practical|
Re^5: multithreaded tcp listener with IO::Socketby BrowserUk (Pope)
|on May 15, 2006 at 16:59 UTC||Need Help??|
This is a known problem. The solution is to pass the fileno( $socket ) bwtween the threads. As this is just an integer, it bypasses the restrictions on shared variables. Once you get the fileno in the destination thread, you can re-open the socket there and use it in the normal ways.
See Re: FileHandles and threads & Re^3: Passing globs between threads for some background and example code, plus some discussion of the caveats. The main problem with this approach is that you have to ensure that the socket returned by accept() does not go out of scope (causing the socket to be closed), before the thread has had chance to reopen it. That's easily achieved by pushing a copy of the socket handle into a (non-shared) array in the accept thread, as well as queueing it.
However, you then have to arrange for those copies to be cleaned up so that you do not leak handles. The method I've evolved to handle that, involves saving copies of the handles in the accept thread as the values in a non-shared hash, keyed by the fileno. Once the client thread has finished with the thread, it closes it's handle and queues the fileno back to the accept thread which use it to close the original handle as a part of the acceppt loop.
It sounds complicated, but is actually easier to code than describe. I'll clean up one of my test programs and post it later today.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.