Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

IO::Socket::UNIX close() discards data when called "too soon"?

by ddzeko (Acolyte)
on Jan 20, 2004 at 14:09 UTC ( #322586=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks,

I'm writing a daemon that will listen on UNIX socket, accept connections, take a request, crunch a bit on it, and spit out a response.

A problem arises when server closes connection after writing out on socket what it had to say. Somehow the data gets lost and client never receives it.

A kludge is to add sleep(1) just before the close. But, this is not acceptable in "production" application because it severely limits throughput to less than 1 msg/sec.

Is there a way to make IO::Socket::UNIX do a REAL FLUSH on that UNIX socket so client could read the data that's been written to it?

Here is the server's code:

#!/usr/bin/perl -w use IO::Socket::UNIX; use strict; my $sockfile = '/tmp/mysocket'; my $r; unlink($sockfile); my $usock = new IO::Socket::UNIX( Type => SOCK_STREAM, Local => $sockfile, Listen => 1) || die "ERROR: $!\n"; while (1) { if (($r) = $usock->accept) { my $out = do_something($r); $r->printflush($out); # sleep 1; # this makes it work $r->close; } } sub do_something { my ($fh) = @_; my ($l) = <$fh>; return uc($l); }

And here is my sample UNIX socket client:

#!/usr/bin/perl -w use IO::Socket::UNIX; my ($sockfile) = shift || die "$0: Socket address required\n"; my $r; my $usock = new IO::Socket::UNIX (Type => SOCK_STREAM, Peer => $sockfile) || die "ERROR: $!\n"; # read stdin and write to socket while(<>) { print $usock $_; } # shut down writing side (server receives EOF) $usock->shutdown(1); $sock->blocking(1); # this does not help # read socket (blocking) and write to stdout while(<$usock>) { print $_; } # shut down reading side $usock->shutdown(0);

I've tried SO_LINGER stuff (snippet found on google/groups) in server...

my $linger = pack('ii', 1, 120); # BSD struct $usock->sockopt(SO_LINGER, $linger);

But to no avail.

PLEASE HELP!!™ :)

Damir Dzeko -- PGP keyID: 38ED4CFF

Replies are listed 'Best First'.
Re: IO::Socket::UNIX close() discards data when called "too soon"?
by pfaut (Priest) on Jan 20, 2004 at 14:58 UTC

    Your server is only reading one line from the client. If your client sends multiple lines, it's possible that the server has closed the socket before the client finishes sending all of his information. In this case, the attempt to print to the socket is probably getting a SIGPIPE aborting your client before it even gets a chance to read the socket. By adding the sleep() call, you have given the client more time to finish writing all of the extra data to the socket and it can complete successfully.

    Try adding $SIG{PIPE} = sub { print "SIGPIPE\n"; }; to your client code somewhere near the top. If 'SIGPIPE' ever gets printed at the client end, then what I described above is happening.

    90% of every Perl application is already written.
    dragonchild
      It should read all the lines, as the readline brackets are in a list assignment - it only returns the first line though. The program works fine here, perl 5.8.2 on linux 2.4.21

        The server reads from the client with the following line in do_something():

        my ($l) = <$fh>;

        That is not a list assignment. If you want to read all of the data from the client, try adding local $/ = undef; before the above line.

        90% of every Perl application is already written.
        dragonchild

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://322586]
Approved by pfaut
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (5)
As of 2020-12-03 11:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    How often do you use taint mode?





    Results (55 votes). Check out past polls.

    Notices?