5

Term :: ReadLine :: Gnuを使用していますが、シグナル処理で問題が発生しました。以下のスクリプトとスクリプトに送信されたTERMシグナルを考えると、ENTERシグナルのハンドラーは、Enterキーが押されるまでトリガーされません。Term :: ReadLine:Perlを使用すると、これは発生しません。

私はTerm::ReadLine :: Gnuが独自の内部シグナルハンドラーを持っていることを読みましたが、率直に言って、それらをどのように扱うかについて途方に暮れています。

http://search.cpan.org/~hayashi/Term-ReadLine-Gnu-1.20/Gnu.pm#Term::ReadLine::Gnu_Variablesでrl_catch_signals変数を0に設定しようとしましたが、役に立ちませんでした。 。理想的には、Gnuシグナルハンドラーを使用したいのですが、それらを無効にすることもできます。

具体的には、Enterキーが押されるのを待つのではなく、シグナルを受信した後にTERMハンドラーをトリガーする必要があります。

どんな助けやアドバイスも確かにありがたいです!

#!/usr/bin/perl

use strict;
use warnings;
use Term::ReadLine;

$SIG{TERM} = sub { print "I got a TERM\n"; exit; };

my $term = Term::ReadLine->new('Term1');
$term->ornaments(0);
my $prompt = 'cmd> ';
while ( defined (my $cmd = $term->readline($prompt)) ) {
    $term->addhistory($cmd) if $cmd !~ /\S||\n/;
    chomp($cmd);
    if ($cmd =~ /^help$/) {
        print "Help Menu\n";
    }
    else {
        print "Nothing\n";
    }
}
4

1 に答える 1

3

これは、perlのデフォルトのシグナルのパラノイド処理によるものです。舞台裏では、perlは呼び出しを開始する前にSIGTERMをブロックし、readline呼び出しが終了すると復元します。詳細については、perlipcの遅延信号を参照してください。

Term::ReadLine::Perlこれらの問題を認識して処理するperlのIOを使用しているため、このバグは発生しません。 Term::ReadLine::Gnu使用しないCライブラリを使用するので、使用します。

これは、次の2つの方法のいずれかで回避できます。

  1. unsafe次のように、スクリプトを実行する前に、環境変数PERL_SIGNALSをに設定します。

    bash$ PERL_SIGNALS=unsafe perl readline-test.pl
    

    注意してください、BEGIN { $ENV{PERL_SIGNALS} = "unsafe"; }それは十分ではありません、それはperl自体が始まる前に設定される必要があります。

  2. POSIX信号機能を使用します。

    #~ $SIG{TERM} = sub { print "I got a TERM\n"; exit; };
    use POSIX;
    sigaction SIGTERM, new POSIX::SigAction sub { print "I got a TERM\n"; exit; };
    

    上記はどちらもLinuxで機能するようです。Windowsや他のユニスについて話すことはできません。また、上記の両方にリスクが伴います。詳細については、perlipcを参照してください。

于 2012-12-09T20:26:57.560 に答える