Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl: Is it possible to undo a SIG{INT} catch?

Tags:

signals

perl

I'm trying to add a catch signal in my Perl program. When a ctrl+C occurs, I'd like a confirmation message, and a user input ( Y or N ). The Y input works fine.

If the user enters N, then essentially I want to "cancel" the ctrl+C command and return to the script.

The code:

$SIG{INT} = \&catchSignal;
$SIG{TERM} = \&catchSignal;

sub catchSignal
{
   my $ans;
   print " Are you sure you want to quit? Y or N:\n";
   $ans = <STDIN>;

   chomp $ans;

   if( $ans eq "Y" )
   {
      exit;
   }
   else
   {
      # Cancel the ctrl+C command
   }

}

Is something like this possible?

like image 576
helloworld95 Avatar asked Dec 03 '19 19:12

helloworld95


1 Answers

Once you have a handler installed the default action of that signal is suppressed and your handler runs instead once that signal comes in. See Signals in perlipc for starters.

So what you show already "cancels" the signal and your program will continue after the handler returns, unless the user confirms the exit of course. Where and how the program continues isn't set in stone, but generally it is from after where it was interrupted.

If a blocking system call gets interrupted by the signal then that call fails with EINTR (errno(3)). These error codes are mostly reflected in %! variable, so when one such call returns an error we can check whether $!{EINTR} is set, and if it is then it may well make sense to restart that call. Thanks to ikegami for a comment.

Precisely what calls have this isn't set firmly, but one can infer it from signal(7) (see footnote).

If they do choose to exit that's a better way to go than being blown out of the water by a signal, since a signal with disposition to stop the program just terminates it. While when a program calls exit that's controlled and one can clean up, exit with a chosen code; also, buffers are flushed, END blocks run.


Except for signals that can't be trapped, STOP (sigstop) and KILL (sigkill) in the first place.

In C we can set SA_RESTART in sigaction(2) to have such calls restarted (see Interruption of system calls... in signal(7) for example), but not with the native %SIG in Perl. There is support in POSIX::sigaction but its use is rather involved and practically undocumented.

like image 61
zdim Avatar answered Oct 03 '22 18:10

zdim