in reply to Re^8: multithreaded tcp listener with IO::Socket
in thread multithreaded tcp listener with IO::Socket

This is untested as I have a bunch of guys with chainsaws and an industrial-sized wood-chipper making enough noise just outside my window to cause the dead to wake and migrate.

Try substituting these replacements:

sub Run { my $self = $_[0]; my( $server, $Qwork, $Qclean, $accept ) = @{ $self }{ qw[ Socket Qwork Qclean Accept ] }; while( local $_ = $server->accept ) { my $fileno = fileno $_; $self->{ Clients }{ $fileno } = $_; my $clientArgs = eval{ join chr(0), $accept->() } || ''; $Qwork->enqueue( "$fileno\0$clientArgs" ); while( my $fno = $Qclean->dequeue() ) { #warnf "Cleanup of %d\n", $fno; close delete $self->{ Clients }{ $fno }; } } } sub _thread { #warnf "Starting thread %d\n", threads->tid; my( $userCode, $Qwork, $Qin, $Qclean ) = @_; while( my $work = $Qwork->dequeue() ) { my( $fileno, @args ) = split chr(0), $work; open my $client, '+<&=' . $fileno or cluck "Failed to dup $fileno in ${ \threads->tid } : $! +\n" and next; $Qclean->enqueue( $fileno ); $userCode->( $client, $Qin, @args ); close $client; } }

The basic problem is that your client won't attempt to move on to making the next connection until both copies of the socket are closed at the server; but the Accept loop copy of the socket won't get closed until someone (your client or another client), make another connection. In a reasonably active system, another client connecting causes the accept loop to cycle and the cleanup occurs; but on a system with only a single client that obviously can't happen.

The solution above avoids that by having the accept loop wait for the client thread to queue the fileno back for cleanup, and then closing its copy of the socket immediately. I've also made the client thread queue the fileno back as soon as it has duped it, to minimise the impact upon the accept loop. It's not a perfect solution for performance, but then using Perl for a server is never going to be the ultimate high performance solution.

I'll try to test this locally, and maybe come up with something better, once the ambient nose level here drops below 100dB; but please do feed back your findings.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
RIP an inspiration; A true Folk's Guy

Replies are listed 'Best First'.
Re^10: multithreaded tcp listener with IO::Socket
by txemy (Initiate) on Nov 15, 2010 at 12:52 UTC

    Yes, this make it work.In the previous post I forgot to say I also had the client thread enqueuing the "you can close this fd" message on Qclean as soon as it opened it's copy .

    Thanks a lot again. (and try to gather some wood chips when they finish : small ones are quite good as the first step in making a good fire !. Enjoy the Autumn :-)