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

I am attempting to create a perl server to listen on a Unix socket. I am creating the socket by:
$client->{socket} = IO::Socket::UNIX->new(Type => SOCK_STREAM, Listen +=> 5, Local => $filename); chmod 777, $filename;
I then add it to my IO::Select by:
$sel->add($client->{socket});
and attempt to wait for a connection by:
while($sel->can_read) { ... }
1. %client is just a hash 2. The file pointed to by $filename does not exist before the call to IO::Socket::UNIX->new and does exist after, so it is getting created 3. The directory where I am creating the file has been chmod'd 777 to ensure this is not a permissions issue. Whenver I reach the while clause, the program immediately ends. If I use the Komodo debugger to step through the code, it ends in IO::Select at the line:
defined ($r) && (select($r, undef, undef, $timeout) > 0)) ? handles(&v +ec, $r) : ();
handles is not being called and it's not returning the empty array, it's simply ending the program. I've tried catching an exception with a try/catch block, but got nothing. Any idea what's going on here?

Replies are listed 'Best First'.
Re: Problems with IO::Select
by ikegami (Patriarch) on Jul 02, 2006 at 17:56 UTC

    Try printing $! after the call to can_read. select should set it.

    Speaking of error checking,
    $client->{socket} = IO::Socket::UNIX->new(...);
    should be
    $client->{socket} = IO::Socket::UNIX->new(...)
       or die("Unable to open socket: $!\n");

      Thanks for the info. Putting print $! directly after the while statement produced nothing, so I added an END block to the code and put print $! in it. The only thing printed was "Interrupted System Call" which still leaves me not knowing what the heck is going on with it, but hopefully tells one of you gurus what I'm doing wrong.

        That message is from something that happened between the while and the END — possibly something internal — not something from the select.

        That $! is blank seems to indicate the select succeeded (for some definition of succeeded), or $r wasn't defined.

        I personally don't know anything about *unix* sockets. Maybe they are different from IP sockets in some important manner for select. I don't think I'll be of any more use to you.

Re: Problems with IO::Select
by ikegami (Patriarch) on Jul 02, 2006 at 22:38 UTC

    shmem pointed out that
    chmod 777, $address;  # sticky + u=rw + g=x + o=x
    should be
    chmod 0777, $address;  # u=rwx + g=rwx + o=rwx
    Read chmod.

      Thank you, but that didn't fix it either.
Re: Problems with IO::Select
by Hue-Bond (Priest) on Jul 02, 2006 at 19:11 UTC

    Please, post a minimal, working example so we can play with it (or in this case, a not working example ;)). If you're lucky, you'll find the problem yourself. Don't forget to check How do I post a question effectively? out.

    --
    David Serrano

      OK. Here goes. This is going to be a LOT briefer than the full code because at this point the program itself is turning out to be a lot bigger than I anticipated. Hopefully, it will give you an idea of what I'm doing, though.
      use strict; use IO::Socket; use IO::Select; #Just opens the configuration file and stuffs all the values into the +%config hash my %config = get_config($ARGV[0] ? $ARGV[0] : "/etc/MailScanManager/Ma +ilScanManager.conf"); my $sel = new IO::Select; #$config{connections} is an array of hashes containing information abo +ut each listening socket #the server should create foreach my $connection (@{$config{connections}}) { if($connection->{socket_type} & IP_SOCKET) { if(!$connection->{socket_address}) { $connection->{socket_addr +ess} = INADDR_ANY; } if(!$connection->{socket_port}) { $connection->{socket_port} = + 7000; } $connection->{socket} = new IO::Socket::INET(Listen => 1, Loca +lPort => $connection->{socket_port}, LocalAddr => $connection->{socke +t_address}) || die("Could not create socket $!");; $sel->add($connection->{socket}); } if($connection->{socket_type} & UNIX_SOCKET) { if(!$connection->{address}) { $connection->{address} = "/var/r +un/MailScanManager/msm.sock"; } unlink($connection->{address}); $connection->{socket} = new IO::Socket::UNIX(Type => SOCK_STRE +AM, Listen => 5, Local => $connection->{address}) || die("Could not c +reate socket $!"); chmod 777, $connection->{address}; $sel->add($connection->{socket}); } } while(my @ready = $sel->can_read) { foreach my $fh (@ready) { #Determine if it's a connection attempt or data sent by a client and a +ct appropriately } }

      I have run this code using TCP/IP sockets and it works perfectly. Select sits and waits for one of the sockets to be readable and then reacts correctly. It only seems to act up when I'm using it with a Unix socket. I haven't tried a combination of the two. I also haven't tried a different path for the Unix socket, but as I stated earlier, it's getting created and the permissions on the directory and file are set to 777, so I don't think that's the problem.

        The request was to "Please, post a minimal, working example so we can play with it". What you posted is neither minimal (we shouldn't need get_config or a config file) nor working (get_config is missing. A sample config file is missing. IP_SOCKET is not defined. UNIX_SOCKET is not defined.)

        The following works (can_read doesn't return) for me. Does it do the same for you? If so, your problem has nothing to do with the socket or select.

        use strict; use warnings; use IO::Socket; use IO::Select; my $sel = IO::Select->new(); my $address = "mysock"; unlink($address); my $sock = IO::Socket::UNIX->new( Type => SOCK_STREAM, Listen => 5, Local => $address ) or die("Unable to create socket $!\n"); chmod 777, $address; $sel->add($sock); while(my @ready = $sel->can_read) { warn; }
Re: Problems with IO::Select
by dirtdart (Beadle) on Jul 03, 2006 at 12:32 UTC

    It seems that this problem is localized to the debugging environment. Whenever I run the test program outside the debugger, it *seems* to work correctly. I haven't had time yet to acutally send and receive information on the socket to verify that it is doing everything that it should. 40 lashes with a wet noodle for me for not verifying that beforehand. Thanks to all those who tried to help with this.