Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Perl Term::ReadLine::Gnu Signal Handling Difficulties

by sgt_b2002 (Initiate)
on Nov 12, 2012 at 20:00 UTC ( [id://1003497]=perlquestion: print w/replies, xml ) Need Help??

sgt_b2002 has asked for the wisdom of the Perl Monks concerning the following question:

Hi everyone,

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 the Gnu_Variables and 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 very much 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)) ) { chomp($cmd); if ($cmd =~ /^help$/) { print "Help Menu\n"; } else { print "Nothing\n"; } }

Replies are listed 'Best First'.
Re: Perl Term::ReadLine::Gnu Signal Handling Difficulties
by Mr. Muskrat (Canon) on Nov 13, 2012 at 06:00 UTC

    You access GNU Readline variables through the Attribs method (with the rl_ stripped). Term::ReadLine::Gnu_Variables

    #!/usr/bin/perl use strict; use warnings; use Term::ReadLine; $SIG{TERM} = sub { print "I got a TERM\n"; exit; }; $SIG{INT} = sub { print "I got a INT\n"; exit; }; # add any additional signal handlers you want my $term = Term::ReadLine->new('Term1'); $term->ornaments(0); my $attribs = $term->Attribs; $attribs->{catch_signals} = 0; # the default is 1 my $prompt = 'cmd> '; while ( defined (my $cmd = $term->readline($prompt)) ) { chomp($cmd); if ($cmd =~ /^help$/) { print "Help Menu\n"; } else { print "Nothing\n"; } }

    Update: Added $SIG{INT}

      Hi Mr. Muskrat

      Thanks for the help. I tried the script you provided and can see how to set the Gnu variables now, but my script still doesn't act how I think it should.

      Given the script you provided, I'll hit control-c to send an INT to the script while at the prompt. I expect to see "I got a INT" right after I hit control-c. Instead, the script stays at the prompt until I hit enter. After hitting enter I see "I got a INT".

      Is this the designed behavior? Ideally, I'd like to have the signal handlers trigger as soon as the signal is received.

      Thanks again for helping me out. :)

        It works for me; that is to say that when I run it and press ctrl-c, it exits with "I got a INT".

        We are going to need more information about the environment where you are testing this. Let's start with operating system, version of Perl, version of Term::ReadLine::Gnu and version of GNU Readline library version should be sufficient for now.

        By the way, it's impolite to cross-post without saying you've cross-posted. http://stackoverflow.com/questions/13316232/perl-termreadlinegnu-signal-handling-difficulties

Re: Perl Term::ReadLine::Gnu Signal Handling Difficulties
by Mr. Muskrat (Canon) on Nov 13, 2012 at 20:32 UTC

    Well, I have been setting up some new servers today (mounting them in the rack, running cables, etc) and haven't have much time to look at this.

    I did find something interesting though. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=160328 It seems that when Perl's safe signals were introduced, it broke Term::ReadLine::Gnu.

    Do you need to use Term::ReadLine::Gnu or can you use Term::ReadLine::Perl (where this still works)?

    If you do need it to use Term::ReadLine::Gnu then perhaps this will work for you. Beware though! It uses unsafe signals so it can cause all sorts of nasty things to happen to the Perl process. Oh and it seems to leave the terminal in an odd state when a signal forces it to bail out.

    #!/usr/bin/perl use strict; use warnings; BEGIN { $ENV{PERL_RL} = 'Gnu'; # or 'Perl' to force which one to use } use Term::ReadLine; use Signal::Safety; my $term = Term::ReadLine->new('Term1'); print "Readline: ", $term->ReadLine, "\n"; $term->ornaments(0); my $attribs = $term->Attribs; $attribs->{catch_signals} = 0; $SIG{TERM} = sub { print "I got a TERM\n"; exit; }; $SIG{INT} = sub { print "I got a INT\n"; exit; }; # add any additional signal handlers you want my $prompt = 'cmd> '; my $cmd = ''; while ( defined $cmd ) { { local $Signal::Safety = 0; # limit the use of unsafe signals $cmd = $term->readline($prompt); } chomp($cmd); if ($cmd =~ /^help$/) { print "Help Menu\n"; } else { print "Nothing\n"; } }
      Thanks a ton for helping me out with this. I see what you mean about unsafe signals, so I'll probably just use Term::ReadLine::Perl instead. I suppose that solves my issues.

      It is somewhat comforting to know that this is just how T:R:Gnu works instead of me doing horribly wrong. ;)

      Since I'm sure I can get things moving along with T:R:Perl, what would be the best way to make sure users are using the T:R:Perl package instead of Gnu? Would it be considered good form to just set the environment variable along with a "use Term::ReadLine::Perl"?

      Thanks again for taking the time to look into this. It was really a stumbling block for me so I appreciate the help. In hindsight I probably should have just moved to T:R:Perl and called it a day, but I got obsessed a bit. ;)

        You're welcome!

        Install Term::ReadLine::Perl and do what the module authors do when they test it.

        BEGIN{ $ENV{PERL_RL} = 'Perl' }; use Term::ReadLine;

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1003497]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (2)
As of 2024-04-20 03:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found