Perl signal handlers are reset in END blocks

◇◆丶佛笑我妖孽 提交于 2019-12-05 21:21:08

This works for me: Re-install the handler in the END block that runs first (last in code).

use warnings;
use strict;
use feature 'say';

$SIG{INT} = sub { say "SIGINT: got zap!" };

#sleep 10;

say "done";

END { say "END, runs last" }
END { say "END, runs next to last. Sleep then print"; sleep 10; say "Woke up."; }

# Executed first in END phase. The sole purpose: to reinstall the handler
END { 
    $SIG{INT} = sub { say "SIGINT in END block, got zap" };
}

When started and Ctrl-C-ed after a few seconds this prints

done.
END, runs next to last. Sleep then print
^CSIGINT in END block, got zap
Woke up.
END, runs last

So you need to add an END block, last in the code, END { $SIG{INT} = 'IGNORE' }.

It appears that the change to "END" ${^GLOBAL_PHASE} removes or otherwise disables the handler.

But once the handler is re-installed in the END phase it is effective throughout. It's cleanest of course to do that in the END block that is executed first.

I will update when (if) I understand more detail and find documentation on this behavior.

perldoc perlmod says:

An "END" code block is executed as late as possible, that is, after perl has finished running the program and just before the interpreter is being exited, even if it is exiting as a result of a die() function. (But not if it's morphing into another program via "exec", or being blown out of the water by a signal--you have to trap that yourself (if you can).)

I expect signal handlers to have been removed just before the interpreter is being exited. Therefore, I am not quite able to see what is surprising or unanticipated.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!