2012-11-09 72 views
5

我正在使用Term :: ReadLine :: Gnu,並遇到信號處理問題。給定下面的腳本和發送給腳本的TERM信號,TERM信號的處理程序不會被觸發,直到後面的按下回車鍵。使用Term :: ReadLine:Perl不會發生。Perl術語:: ReadLine :: Gnu信號處理難點

我讀過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"; 
    } 
} 
+0

我不知道這是否是一個緩衝問題。嘗試從這個答案的解決方案:http://stackoverflow.com/a/7603502/1791055 – titanofold

+1

什麼是\/S || \ n /'應該做的? :-)(與你的實際問題無關,我只注意到它)。請注意,因爲你的兩個管道之間沒有任何東西,所以正則表達式會匹配任何東西,所以!〜將永遠是錯誤的。 – Tanktalus

+0

ysth幫助我在另一篇文章中回答這個問題http://stackoverflow.com/questions/13332908/termreadline-i-need-to-hit-the-up-arrow-twice-to-retrieve-history 原來它是完全的多餘的T:R:G默認爲添加歷史。我會刪除它。 –

回答

3

這是由於Perl的默認的信號處理偏執 - 在幕後,Perl的塊SIGTERM開始readline呼叫之前,當它完成恢復它。有關詳細信息,請參閱Deferred Signals in perlipc

Term::ReadLine::Perl使用perl的IO,它知道這些問題並處理它們,所以你不會看到這個bug。 Term::ReadLine::Gnu使用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或其他unices。另外,上述兩者都有風險 - 請參閱perlipc瞭解詳情。