如何从perl中的IO :: Async :: Loop事件中删除IO :: Async :: Listener(或其通知程序)对象

时间:2012-05-15 16:53:54

标签: perl asyncsocket unix-socket io-socket

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

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

IO :: Async :: Loop提供通过$ loop-> remove($ notifier)从事件循环中删除IO :: Async :: Notifier对象,但创建通知程序由IO :: Async ::内部处理监听器(通过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 个答案:

答案 0 :(得分: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行需要确保SIGINTSIGTERM仍然运行END块,而不是仅仅导致perl进程立即终止

最后,您应该注意,您可以使用更简洁的listen方法,而不是在您的情况下明确创建UNIX套接字,您可以

my $listener = ...
$loop->add( $listener );

$listener->listen(
  addr => {
    family   => "unix",
    socktype => "stream",
    path     => "echo.sock",
  },
);

虽然在这种情况下你仍然需要END阻止。