在C中,信号处理程序只能访问volatile sig_atomic_t
类型的变量。在perl中,运行这种信号处理程序是安全的(和原子的)吗?
my $p = 0;
$SIG{CHLD} = sub {
while (waitpid(-1, WNOHANG) > 0) {
$p--;
}
};
虽然我的主要线程正在使用$p
,例如=
,++
或+=
。
我知道perl使用Safe-Signals但是一个简单的++
或--
单个操作码?什么语言运算符是1操作码?
安全我的意思是什么是原子操作,以便$p
内容不会被破坏。
答案 0 :(得分:4)
在安全信号下,将子信号分配给%SIG
中的信号会导致Perl安装一个只增加计数器的信号处理程序。在Perl操作码之间检查此计数器。 [1] 只有这时才调用Perl子。
预增量,后增量,预减量和后递减都是Perl操作码,因此它们不会被信号中断。
$ perl -MO=Concise,-exec -e'my $x; ++$x; --$x; $x++; $x--;'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <0> padsv[$x:1,2] vM/LVINTRO
4 <;> nextstate(main 2 -e:1) v:{
5 <0> padsv[$x:1,2] sRM
6 <1> preinc vK/1
7 <;> nextstate(main 2 -e:1) v:{
8 <0> padsv[$x:1,2] sRM
9 <1> predec vK/1
a <;> nextstate(main 2 -e:1) v:{
b <0> padsv[$x:1,2] sRM
c <1> preinc[t2] vK/1
d <;> nextstate(main 2 -e:1) v:{
e <0> padsv[$x:1,2] sRM
f <1> predec[t3] vK/1
g <@> leave[1 ref] vKP/REFC
-e syntax OK
我们还必须看看如何在信号处理程序之外使用$p
来确定它是否安全。例如,如果信号处理程序外部的代码执行了以下操作,则会出现问题,因为这可能会中断。
$p = $p - 1;
这是安全的:
my %children;
$SIG{CHLD} = sub {
local ($?, $!, $^E);
while ( ( my $pid = waitpid(-1, WNOHANG) ) > 0 ) {
my $child = $children{$pid}
or next; # ?!?
$child->{exit_status} = $?;
}
};
while (1) {
...
for my $pid (keys(%children)) {
my $child = $children{$pid};
defined( my $exit_status = $child->{exit_status} )
or next;
delete($children{$pid});
...
}
...
}