2

IO::Socket::UNIX を使用して UNIX ドメイン ソケットを作成し、それを IO::Async::Listener のインスタンスに渡して、ソケットでのリッスンとデータ受信時の通知を処理するコードがあります。次に、IO::Async::Listener が IO::Async::Loop イベント ループ インスタンスに追加されます。もちろん、ソケットは制御されたマネージャーで動的に作成されます。

特定の条件で、イベントループからソケットを削除したい (完全に削除するか、可能であれば他の条件で一時的に無効にする) 方法がわかりません。

IO::Async::Loop は $loop->remove( $notifier ) を介してイベントループから IO::Async::Notifier オブジェクトを削除することを提案しますが、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

ここに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確実に実行し続けるために必要です。SIGINTSIGTERMENDperl

最後に、ケースでソケットをlisten明示的に作成するのではなく、より適切な形式のメソッドを使用できることに注意してください。UNIX

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

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

ただし、この場合もENDブロックが必要になります。

于 2012-05-16T13:25:00.083 に答える