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

Hi monks,

I am struggling with IO::Socket::Unix. My issue can be summarized as follow:

I can accept that the writer can not write any more on the socket once it has been closed by the reader (although I would have guessed it should not matter), but I have not found a way in the writer to check if the socket is still usable. Is there something I can use for this purpose?

Here are my test scripts, trimmed down to the bare minimum showing this behavior:

Reader:

#!/usr/bin/perl use strict; use warnings; use IO::Socket::UNIX; my $SOCK = '/home/lomig/dev/imliner/run/tst.sock'; unlink $SOCK if -e $SOCK; my $read = IO::Socket::UNIX ->new ( Local => $SOCK, Listen=> SOMAXCONN, Type => SOCK_STREAM, Reuse =>1, ); $read || die "No read socket: $!\n"; print 'Read inode = ', (stat($read->hostpath()))[1], "\n"; my $client = $read->accept(); while (<$client>) { print "read: $_"; last if $_ =~ /2/; #exit after 3rd message } $client->close(); $read->close(); exec $0; # restart itself

Writer:

#!/usr/bin/perl use strict; use warnings; use IO::Socket::UNIX; my $write = IO::Socket::UNIX ->new( Peer => '/home/lomig/dev/imliner/run/tst.sock', Type => SOCK_STREAM, ) ; $write || die "No write socket: $!\n"; for (0..2) { print 'Write connected? ', $write->connected() ? 'yes' : 'no', "\n"; print 'Write opened? ' , $write->opened() ? 'yes' : 'no', "\n"; print 'Write errored? ' , $write->error() ? 'yes' : 'no', "\n"; print 'Write peerpath: ' , $write->peerpath(), "\n"; print'inode : ' , (stat($write->peerpath()))[1], "\n"; foreach my $i (0..2) { eval {print $write "Hi $i\n";}; if ($@) {print "Write issue: $@\n";} # *never* reached } print "Go to sleep while the reader restarts itself, then loop again +\n"; sleep 2; } $write->close();

Writer's output:

Write connected? yes Write opened? yes Write errored? no Write peerpath: /home/lomig/dev/imliner/run/tst.sock inode : 1517896 Go to sleep while the reader restarts itself Write connected? yes Write opened? yes Write errored? no Write peerpath: /home/lomig/dev/imliner/run/tst.sock inode : 1517896

And that's it, not segfault, exception, nothing.

I am using perl 5.10.0-23 on debian unstable, up to date.

Thank you very much for any help or pointer to help me understand this.

Replies are listed 'Best First'.
Re: IO::Socket::UNIX unexpected death
by targetsmart (Curate) on Jun 30, 2009 at 11:09 UTC
    the writer dies, without any message, explanation or exception
    Did you tried trapping signal SIGPIPE?

    I have not found a way in the writer to check if the socket is still usable. Is there something I can use for this purpose?
    eof might help you to find out whether the filehandle is closed or open, before doing further write on the filehandle


    Vivek
    -- 'I' am not the body, 'I' am the 'soul', which has no beginning or no end, no attachment or no aversion, nothing to attain or lose.
      Hi,

      Did you tried trapping signal SIGPIPE?
      I did not try that, and SIGPIPE can be and indeed is trapped on the second print. From there, I should be able to properly deal with this case. Thanks a lot for this! I am surprised there is no other OOish way to find that out before the actual write, though.

      eof might help you to find out whether the filehandle is closed or open
      eof ($write) is actually blocking in the write script, so not really of use to me in this instance. It might be because of the way the socket is opened, only for writing, not for reading?

      Thanks a lot for you insight.

Re: IO::Socket::UNIX unexpected death
by tprocter (Sexton) on Jun 30, 2009 at 11:40 UTC
    It looks like you are trying to use the reader as a server since it's the one calling 'accept'. The process that continues running should have that role.

    Otherwise, the socket object ($write) loses its counterpart when the reader exits, and would have to reconnect.

    Suggest: move your accept call to the server side. Servers usually check for new connections and 'accept' them, or dedicate a thread to blocking accept calls and using worker threads to handle the connections. Unix socket files may be slightly different (I haven't used them much), but I expect the principles to be the same.

      Hi, thanks for your suggestion.

      The accept call will indeed be server-side. Actually, there will be 2 services speaking to each other through 2 sockets. This case (reader being restarted) is an exceptional case, but it happened during my tests and I wanted to be sure to handle that properly before going live.

      the socket object ($write) loses its counterpart when the reader exits, and would have to reconnect.
      It makes perfect sense, but I am surprised there is no other way than trapping SIGPIPE to catch this.