在信号处理程序中访问/修改共享变量是否安全?

时间:2017-08-18 17:52:44

标签: perl signals opcode

在C中,信号处理程序只能访问volatile sig_atomic_t类型的变量。在perl中,运行这种信号处理程序是安全的(和原子的)吗?

my $p = 0;

$SIG{CHLD} = sub {
    while (waitpid(-1, WNOHANG) > 0) {
        $p--;
    }
};

虽然我的主要线程正在使用$p,例如=+++=

我知道perl使用Safe-Signals但是一个简单的++--单个操作码?什么语言运算符是1操作码?

安全我的意思是什么是原子操作,以便$p内容不会被破坏。

1 个答案:

答案 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});

      ...
   }

   ...
}
  1. 我认为在更新版本的Perl中,它的粒度更小。