Setup: kernel: 4.1.16-v7+ OS: armv7l GNU/Linux (mostly debian)
This is perl 5, version 20, subversion 2 (v5.20.2) built for arm-linux-gnueabihf-thread-multi-64int
A larger perl code has a part of external process which sometimes does not respond within a certain timelimit. When this error occurs the "main" subroutine gets restarted via signal_handler command "restartservice"
During debugging this issue i found numerous descriptions about signal handling and especially reinitialising a signal handler once you have used it.
and http://www.perlmonks.org/?node_id=440900
qouting:
Not all platforms automatically reinstall their (native) signal handlers >after a signal delivery. This means that the handler works only the first >time the signal is sent. The solution to this problem is to use "POSIX" >signal handlers if available, their behaviour is well-defined.
So i tried to figure out the POSIX way of doing it, did not found a solution until i reproduced the example from http://perldoc.perl.org/perlipc.html and enhanced it with my "restartservice" subroutine.
My issue seems to be: I cannot call an already defined subroutine when a signal_handler gets executed.
Example:
#!/usr/bin/perl
use warnings;
use strict;
sub restartservice()
{
print "alarm reached\n";
main();
};
sub main()
{
while (1){
print "while loop\n";
eval {
#local $SIG{ALRM} = sub { print "alarm main\n"; main();" };#fails
local $SIG{ALRM} = sub { print "alarm main\n"; next; };#works
#local $SIG{ALRM} = \&restartservice; #does not work ,proove below
alarm 2;
sleep 5;# here i would use my normal code which sometimes hangs
alarm 0;
};
};
}
main();
Output proove of working situation:
perl perlalarm.pl
while loop
alarm main
Exiting subroutine via next at perlalarm.pl line 17.
Exiting eval via next at perlalarm.pl line 17.
while loop
alarm main
Exiting subroutine via next at perlalarm.pl line 17.
Exiting eval via next at perlalarm.pl line 17.
while loop
alarm main
...
Output proove of not working situation:
perl perlalarm.pl
while loop
alarm reached
while loop
while loop
while loop
I would like to know what i have to do to get a subroutine working in that signal handler.
Once you replace
main()
withnext
in the named subroutine to make it equivalent to the anonymous one, it starts working, too.Generally, signals are masked when you are inside a signal handler, unless you set the
SA_NODEFER
flag through asigaction
call (in perl: POSIX::SigAction).So, your second invocation of
main()
from within the signal handler runsmain()
with SIGALRM blocked. Your execution looks like this:Good practice is to do something very small and discrete in a signal handler, like set a flag or, sometimes, throw an exception. In perl, the
eval{}+alarm
idiom is usually the latter: