Как удалить объект IO::Async::Listener (или его уведомителя) из события IO::Async::Loop в perl
У меня есть кусок кода, который создает сокет домена UNIX с помощью IO::Socket::UNIX и передает его экземпляру IO::Async::Listener для обработки прослушивания сокета и уведомления о получении данных. Затем IO::Async::Listener добавляется к экземпляру цикла событий IO::Async::Loop. Разумеется, сокеты создаются динамически в управляемом менеджере.
При определенных условиях я хотел бы удалить сокет из цикла событий (полностью удалить его или временно отключить его при других условиях, если это возможно), но я не знаю как.
IO::Async::Loop предлагает удалить объекты IO::Async::Notifier из цикла событий с помощью $loop->remove( $notifier), но создание уведомителя было обработано внутри IO::Async::Listener (через IO:: Async:: Stream, я полагаю?). Даже на Ctrl-C моего скрипта файл сокета не удаляется, мне просто нужно вручную close $socket and unlink( $path )
файла сокета?
Вот абстрактный код желаемого поведения:
#!/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;
}
1 ответ
Кажется, у вас есть два связанных вопроса.
Вы можете удалить объект слушателя из цикла, используя цикл remove
метод:
$loop->remove( $listener )
Однако удаление слушателя из цикла не приведет к отсоединению узла сокета от файловой системы. Для этого вам понадобится unlink
код, который вы предложили.
Лично в таком коде, который создает подобные сокеты, я использую END
блок:
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 };
$SIG
линия требуется, чтобы убедиться, что SIGINT
а также SIGTERM
еще запустить END
блокировать, а не просто вызывая perl
Процесс немедленно прекратить.
Наконец, вы должны отметить, что вы можете использовать более аккуратную форму listen
метод, а не явно создавая UNIX
гнездо в вашем случае можно просто
my $listener = ...
$loop->add( $listener );
$listener->listen(
addr => {
family => "unix",
socktype => "stream",
path => "echo.sock",
},
);
Хотя опять же в этом случае вам все равно понадобится END
блок.