我经常fork在也有END { ... }块的程序中使用:
...
END { &some_cleanup_code }
...
my $pid = fork();
if (defined($pid) && $pid==0) {
&run_child_code;
exit 0;
}
Run Code Online (Sandbox Code Playgroud)
子进程在END {}退出时执行块,但通常我不希望发生这种情况.有没有办法阻止子进程END在退出时调用块?除此之外,有没有办法让程序"知道"它是一个子进程,所以我可以说类似的东西
END { unless (i_am_a_child_process()) { &some_cleanup_code } }
Run Code Online (Sandbox Code Playgroud)
?
cjm*_*cjm 18
我认为没有办法阻止END块在分叉进程中运行,但这应该让你检测它:
my $original_pid; BEGIN { $original_pid = $$ }
... # Program goes here
END { do_cleanup() if $$ == $original_pid }
Run Code Online (Sandbox Code Playgroud)
eph*_*ent 15
exit()函数并不总是立即退出.它首先调用任何已定义的
END例程,但这些END例程本身可能不会中止退出.同样,在真正退出之前调用任何需要调用的对象析构函数.如果这是一个问题,您可以调用POSIX:_exit($status)以避免END和析构函数处理.有关详细信息,请参阅perlmod.
use B;
@{; eval { B::end_av->object_2svref } || [] } = ();
Run Code Online (Sandbox Code Playgroud)
我以为有一个Devel :: module也允许你这样做,但我现在找不到它.
当然,如果您使用可能正在使用END块的任意模块用于自己的目的,则无法安全地执行此操作...
(由OP编辑)您可以使用控件来控制END块B::end_av.作为概念验证:
END { print "This is the first end block.\n"; }
my $END_block_2_line = __LINE__ + 1;
END { print "This is the second end block.\n"; }
END { print "This is the third end block.\n" }
sub disable_specific_END_block {
use B;
my ($file, $line) = @_;
eval {
my @ENDs = B::end_av->ARRAY;
for (my $i=$#ENDs; $i>=0; $i--) {
my $cv = $ENDs[$i];
if ($cv->START->file eq $file && $cv->START->line == $line) {
splice @{B::end_av->object_2svref}, $i, 1;
}
}
};
}
disable_specific_END_block(__FILE__, $END_block_2_line);
Run Code Online (Sandbox Code Playgroud)
$ perl endblocks.pl
This is the third end block.
This is the first end block.
Run Code Online (Sandbox Code Playgroud)
通常这样的东西对于我需要的东西来说太过分了,但是我可以看到一些这样的情况会派上用场.
从某种意义上讲,在fork儿童中避免这种情况的习惯方法是:
exec "true";
Run Code Online (Sandbox Code Playgroud)
或者,如果您发现太不值得信任,这些都可以工作,甚至可以使用use strict:
exec $^X => -eexit;
exec ~~echo => ~~-echo;
exec ~~echo => !!-echo;
Run Code Online (Sandbox Code Playgroud)
和拟声词
exec reverse reverse echo => ~~-echo;
Run Code Online (Sandbox Code Playgroud)
Rebmemer-在Perl中,没有愚蠢的问题,但可能有愚蠢的答案...... ☺
$ perl -Mstrict '-leprint ucfirst lc reverse-Remember'
Run Code Online (Sandbox Code Playgroud)