Sgt*_*t B 5 perl readline signal-handling
我正在使用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处理程序在接收到信号后触发,而不是等待按下回车键.
任何帮助或建议当然感谢!
#!/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";
}
}
Run Code Online (Sandbox Code Playgroud)
这是由于 perl 对信号的默认偏执处理 - 在幕后,perl 在开始调用之前阻止 SIGTERM readline,并在调用完成时恢复它。有关详细信息,请参阅perlipc 中的延迟信号。
Term::ReadLine::Perl使用perl的IO,它知道这些问题并处理它们,所以你不会看到这个错误。 Term::ReadLine::Gnu使用 C 库,而 C 库没有,所以你就这样做了。
您可以使用以下两种方法之一解决此问题:
unsafe在运行脚本之前将环境变量 PERL_SIGNALS 设置为:
bash$ PERL_SIGNALS=unsafe perl readline-test.pl
Run Code Online (Sandbox Code Playgroud)
注意,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; };
Run Code Online (Sandbox Code Playgroud)
上面两个似乎都可以在 Linux 中工作;不能代表 Windows 或其他操作系统。此外,上述两种方法都存在风险 - 请参阅 perlipc 了解详细信息。
| 归档时间: |
|
| 查看次数: |
621 次 |
| 最近记录: |