I have a piece of code that creates a UNIX domain socket using IO::Socket::UNIX and gives it to an instance of IO::Async::Listener to handle listening on the socket and notifying on receiving data. The IO::Async::Listener, then, is added to a IO::Async::Loop event loop instance. The sockets are created dynamically in a controlled manager, of course.
On a certain condition, I'd like to remove the socket from the event loop (completely delete it, or temporarily disable it on other conditions if possible) but I don't know how.
IO::Async::Loop offers to remove IO::Async::Notifier objects from the event loop via $loop->remove( $notifier ) but creating the notifier was handled internally by IO::Async::Listener (via IO::Async::Stream, I presume?). Even on Ctrl-C of my script, the socket file is not deleted, do I just have to manually close $socket and unlink( $path )
of the socket file?
Here's an abstract code of the desired behavior:
#!/usr/bin/perl
use IO::Async::Loop;
use IO::Async::Listener;
use IO::Socket::UNIX;
my $loop = IO::Async::Loop->new;
my $listener = IO::Async::Listener->new(
on_stream => sub {
my ( undef, $stream ) = @_;
$stream->configure(
on_read => sub {
my ( $self, $buffref, $eof ) = @_;
$self->write( $buffref );
$buffref = "";
return 0;
},
);
$loop->add( $stream );
},
);
$loop->add( $listener );
my $socket = IO::Socket::UNIX->new(
Local => "echo.sock",
Listen => 1,
) || die "Cannot make UNIX socket - $!\n";
$listener->listen(
handle => $socket,
);
my $condition = true;
while($condition) {
// this is probably wrong
$loop->remove( $listener );
$condition = false;
}
You seem to have two related questions here.
You can remove the listener object from the loop by using the loop's remove
method:
$loop->remove( $listener )
However, removing the listener from the loop won't unlink the socket node from the fileystem. For that you will need the unlink
code you suggested.
Personally, in such code as creates sockets like this, I make use of an END
block:
my $path = "echo.sock";
my $socket = IO::Socket::UNIX->new(
Local => $path,
Listen => 1,
) || die "Cannot make UNIX socket - $!\n";
END { $socket and unlink $path }
$SIG{INT} = $SIG{TERM} = sub { exit 1 };
The $SIG
line is required to ensure that SIGINT
and SIGTERM
still run the END
block, rather than just causing the perl
process to immediately terminate.
Finally, you should note that you can use a neater form of the listen
method, rather than explicitly creating the UNIX
socket in your case, you can just
my $listener = ...
$loop->add( $listener );
$listener->listen(
addr => {
family => "unix",
socktype => "stream",
path => "echo.sock",
},
);
Though again in this case you will still need the END
block.