Perl Term :: ReadLine :: Gnu信号处理困难 [英] Perl Term::ReadLine::Gnu Signal Handling Difficulties

查看:95
本文介绍了Perl Term :: ReadLine :: Gnu信号处理困难的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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库.

您可以使用以下两种方法之一解决此问题:

  1. 在运行脚本之前将环境变量PERL_SIGNALS设置为unsafe,如下所示:

    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.

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:

  1. 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.

  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆