2

我有一段代码使用 IO::Socket::UNIX 创建一个 UNIX 域套接字,并将其提供给 IO::Async::Listener 的一个实例,以处理监听套接字并通知接收数据。然后,将 IO::Async::Listener 添加到 IO::Async::Loop 事件循环实例中。当然,套接字是在受控管理器中动态创建的。

在某种情况下,我想从事件循环中删除套接字(完全删除它,或者如果可能的话在其他情况下暂时禁用它)但我不知道如何。

IO::Async::Loop 提供通过 $loop->remove( $notifier ) 从事件循环中删除 IO::Async::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;
}
4

1 回答 1

2

您似乎在这里有两个相关的问题。

您可以使用循环的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块。

于 2012-05-16T13:25:00.083 回答