2012-11-09 42 views
5

Tôi đang sử dụng thuật ngữ :: ReadLine :: Gnu và đã gặp phải sự cố khi xử lý tín hiệu. Với kịch bản bên dưới và tín hiệu TERM được gửi tới tập lệnh, trình xử lý tín hiệu TERM không được kích hoạt cho đến khi sau phím enter được nhấn. Sử dụng thuật ngữ :: ReadLine: Perl điều này không xảy ra.Perl Term :: ReadLine :: Gnu Xử lý tín hiệu Khó khăn

Tôi đã đọc thuật ngữ đó :: ReadLine :: Gnu có bộ xử lý tín hiệu nội bộ riêng của nó, nhưng thẳng thắn tôi thua lỗ về cách làm việc với chúng.

Tôi đã xem xét http://search.cpan.org/~hayashi/Term-ReadLine-Gnu-1.20/Gnu.pm#Term::ReadLine::Gnu_Variables đã thử đặt biến rl_catch_signals thành 0, nhưng điều đó không giúp ích gì. Lý tưởng nhất, tôi muốn làm việc với các trình xử lý tín hiệu Gnu, nhưng tôi sẽ giải quyết cho việc vô hiệu hóa chúng.

Để hoàn toàn cụ thể, tôi cần trình xử lý TERM để kích hoạt sau khi nhận được tín hiệu thay vì đợi nhập phím.

Bất kỳ trợ giúp hoặc lời khuyên nào chắc chắn được đánh giá cao!

#!/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

Tôi tự hỏi đây có phải là vấn đề về đệm hay không. Hãy thử giải pháp từ câu trả lời này: http://stackoverflow.com/a/7603502/1791055 – titanofold

+1

'/ \ S || \ n /' phải làm gì? :-) (Không liên quan đến câu hỏi thực tế của bạn, tôi chỉ nhận thấy nó.) Lưu ý rằng bởi vì không có gì giữa hai ống của bạn, regex sẽ phù hợp với bất cứ điều gì, vì vậy! ~ Sẽ luôn luôn là sai. – Tanktalus

+0

ysth đã giúp tôi trả lời câu hỏi này trong một bài đăng khác http://stackoverflow.com/questions/13332908/termreadline-i-need-to-hit-the-up-arrow-twice-to-retrieve-history Biến nó hoàn toàn thừa như T: R: G không có tính năng mặc định. Tôi sẽ loại bỏ nó. –

Trả lời

3

Điều này là do perl của mặc định xử lý hoang tưởng của các tín hiệu - đằng sau hậu trường, khối perl SIGTERM trước khi bắt đầu cuộc gọi readline và khôi phục nó khi nó kết thúc. Xem Deferred Signals in perlipc để biết chi tiết.

Term::ReadLine::Perl sử dụng IO của perl, biết về các vấn đề này và giao dịch với chúng, vì vậy bạn không thấy lỗi này với nó. Term::ReadLine::Gnu sử dụng thư viện C, thư viện này không sử dụng.

Bạn có thể làm việc xung quanh này với một trong hai phương pháp:

  1. thiết lập môi trường PERL_SIGNALS biến để unsafe trước khi chạy kịch bản, như trong:

    bash$ PERL_SIGNALS=unsafe perl readline-test.pl 
    

    Note, BEGIN { $ENV{PERL_SIGNALS} = "unsafe"; } không phải là đủ, nó cần phải được thiết lập trước khi chính nó bắt đầu.

  2. Sử dụng POSIX chức năng tín hiệu:

    #~ $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; }; 
    

    Cả ở trên dường như làm việc trong Linux; không thể nói cho Windows hoặc các thông báo khác. Ngoài ra, cả hai điều trên đều có rủi ro - hãy xem perlipc để biết chi tiết.

Các vấn đề liên quan