Perl Term :: ReadLine :: Gnu信号处理困难 [英] Perl Term::ReadLine::Gnu Signal Handling Difficulties
问题描述
我正在使用Term :: ReadLine :: Gnu并遇到信号处理问题.给定以下脚本并向该脚本发送了TERM信号,直到之后按下回车键,才触发TERM信号的处理程序.使用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信号处理程序一起使用,但我也将决定禁用它们.
确切地说,我需要TERM处理程序在接收到信号后触发,而不是等待按下Enter键.
任何帮助或建议都非常感谢!
#!/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";
}
}
这是由于perl对信号的默认偏执处理-在后台,perl在开始readline
调用之前阻止了SIGTERM并在完成后将其恢复.有关详细信息,请参见 perlipc中的延迟信号./p>
Term::ReadLine::Perl
使用perl的IO,该IO了解这些问题并进行处理,因此您不会看到此错误. Term::ReadLine::Gnu
使用C库,但不使用C库.
您可以使用以下两种方法之一解决此问题:
-
在运行脚本之前将环境变量PERL_SIGNALS设置为
unsafe
,如下所示:bash$ PERL_SIGNALS=unsafe perl readline-test.pl
注意,
BEGIN { $ENV{PERL_SIGNALS} = "unsafe"; }
还不够,需要在perl本身启动之前进行设置. -
使用
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.
I'm using Term::ReadLine::Gnu and have run into a problem with signal handling. Given the script below and a TERM signal sent to the script, the handler for the TERM signal is not triggered until after the enter key is pressed. Using Term::ReadLine:Perl this does not occur.
I've read that Term::ReadLine::Gnu has its own internal signal handlers, but frankly I'm at a loss as to how to work with them.
I've reviewed http://search.cpan.org/~hayashi/Term-ReadLine-Gnu-1.20/Gnu.pm#Term::ReadLine::Gnu_Variables tried setting the rl_catch_signals variable to 0, but that didn't help. Ideally, I'd like to work with the Gnu signal handlers, but I'll settle for disabling them too.
To be absolutely specific, I need the TERM handler to trigger after the signal is received instead of waiting for the enter key to be pressed.
Any help or advice is certainly appreciated!
#!/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";
}
}
This is due to perl's default paranoid handling of signals - behind the scenes, perl blocks SIGTERM before starting the readline
call and restores it when it's finished. See Deferred Signals in perlipc for the details.
Term::ReadLine::Perl
uses perl's IO, which knows about these issues and deals with them, so you don't see this bug with it. Term::ReadLine::Gnu
uses the C library, which doesn't, so you do.
You can work around this with one of two methods:
set the environment variable PERL_SIGNALS to
unsafe
before running the script, as in:bash$ PERL_SIGNALS=unsafe perl readline-test.pl
Note,
BEGIN { $ENV{PERL_SIGNALS} = "unsafe"; }
isn't enough, it needs to be set before perl itself starts.Use
POSIX
signal functions:#~ $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; };
Both the above seem to work in Linux; can't speak for Windows or other unices. Also, both of the above come with risks - see perlipc for the details.
这篇关于Perl Term :: ReadLine :: Gnu信号处理困难的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!