I am trying to write Perl code that does two-way communication over a Unix socket. It needs to do the following things:
- Client code sends a request over the socket
- Server code reads the request
- Server performs any actions that should happen immediately
- Server creates a new thread to do additional actions that may take a long time
- Server sends response over the socket
- Client receives response
- The new thread continues to work after the response has been sent
I have gotten most of this to work now, but with one problem. Steps 1 - 5 work fine, but at step 6, the client is unable to read the response until AFTER the thread has exited. (even though the response was sent more-or-less immediately) Any idea what I'm doing wrong?
I'm using Perl 5.10.1 on Ubuntu Lucid.
Here's an example:
Client code:
#!/usr/bin/perl
use strict;
use Socket;
my $socket_name = 'catsock';
my $client_message = "Hello server, this is the client.";
my $SOCK;
socket($SOCK, PF_UNIX, SOCK_STREAM, 0) or die "socket: $!";
connect($SOCK, sockaddr_un($socket_name)) or die "connect: $!";
$| = 1, select $_ for select $SOCK; # turn on autoflush
print $SOCK $client_message; # send the message
shutdown($SOCK,1); # finished writing
print "sent: $client_message\n";
my $server_message = do { local $/; <$SOCK> }; # get the response
print "recieved: $server_message\n\n";
Server code
#!/usr/bin/perl
use strict;
use Socket;
use threads;
use threads::shared;
sub threadfunc
{
print " waiting 5 seconds in new thread...\n";
sleep(5);
print " exiting thread...\n\n";
}
my $server_message = "Hello client, this is the server.";
my $socket_name = 'catsock';
my $SERVER;
my $CLIENT;
socket($SERVER, PF_UNIX, SOCK_STREAM, 0) or die "socket: $!";
unlink($socket_name);
bind($SERVER, sockaddr_un($socket_name)) or die "bind: $!";
chmod(0660, $socket_name);
listen($SERVER, SOMAXCONN) or die "listen: $!";
print "server started on $socket_name\n\n";
while(1) {
accept($CLIENT, $SERVER);
my $client_message = do { local $/; <$CLIENT> }; # grab entire message
print "recieved: $client_message\n";
print "creating new thread...\n";
my $thr = threads->create(\&threadfunc);
$thr->detach();
print $CLIENT $server_message; # send the response
print "sent: $server_message\n\n";
close $CLIENT;
}
When I run this, the following things happen:
- Client sends "Hello server, this is the client."
- Server receives client's message
- Server creates a new thread
- Server sends "Hello client, this is the server."
- Client should receive the message now, but it does not.
- New thread on server sleeps for 5 seconds
- Thread exits
- Now the client receives the server's message, even though it was sent 5 seconds ago. Why?
$CLIENT
to autoflush after the accept? – Eric Strom$CLIENT
and the connection doesn't close until all the copies are out of scope, maybe), but it doesn't delay the write to$CLIENT
. – mob