我正在尝试决定从为x86_64-linux-thread-multi
构建的perl(v5.14.2)中的信号处理程序访问公共(读取:处理程序代码和程序的其余部分之间的共享)数据结构是否安全,但目标平台是solaris11)。
perlipc包含以下示例代码:
use POSIX ":sys_wait_h"; # for nonblocking read
my %children;
$SIG{CHLD} = sub {
# don't change $! and $? outside handler
local ($!, $?);
my $pid = waitpid(-1, WNOHANG);
return if $pid == -1;
return unless defined $children{$pid};
delete $children{$pid};
cleanup_child($pid, $?);
};
while (1) {
my $pid = fork();
die "cannot fork" unless defined $pid;
if ($pid == 0) {
# ...
exit 0;
} else {
$children{$pid}=1;
# ...
system($command);
# ...
}
}
因此,从while循环和处理程序访问%children
。这似乎没有问题:
pid
pid
键入(我不确定$childer{pid}=1
是否是原子的,可中断而不会导致损坏。)现在,我正在尝试在我的处理程序中做更多事情:
my %categoryForPid;
my %childrenPerCategory;
$SIG{CHLD} = sub {
# ... acquire pid like above
my $category = $categoryForPid{$pid};
$childrenPerCategory{$category}--;
delete $categoryForPid{$pid};
}
while (1) {
# ... same as above
} else {
$children{$pid}=1;
my $category = # ... chose some how
$childrenPerCategory{$category}++;
$categoryForPid{$pid} = $category;
# ...
}
}
这里的想法是:每个孩子都属于某个类别(N到1)。我想跟踪每个类别中有多少个孩子。该信息可以从$categoryForPid
导出,但我认为这也可能存在问题(例如,当执行计算的子程序在求和时被中断时)。
所以我的问题是:
并注意到:
除了@goldilocks发现的问题和他提出的解决方案之外,我现在在更新数据结构时阻止信号以确保“原子性”:
my $sigset = POSIX::SigSet->new(SIGCHLD);
sub ublk {
unless (defined sigprocmask(SIG_UNBLOCK, $sigset)) {
die "Could not unblock SIGCHLD\n";
}
}
sub blk {
unless (defined sigprocmask(SIG_BLOCK, $sigset)) {
die "Could not block SIGCHLD\n";
}
}
while (1) {
# ... same as above
} else {
blk;
$children{$pid}=1;
my $category = # ... chose some how
$childrenPerCategory{$category}++;
$categoryForPid{$pid} = $category;
ublk;
# ...
}
}
答案 0 :(得分:1)
对我来说似乎是一个坏主意。 IPC :: Semaphore 可能解决问题,如果你能让它们在信号处理程序中正常工作 - 如果控制权在处理程序退出之前没有返回,你就是运气不好但是,您可以通过锁定父级并让子级等待锁定直到初始化完成来解决这个问题。处理程序不涉及信号量。我认为你实际上只需要一把锁。无论如何:
my @array = (1..10);
my $x = 'x';
$SIG{'USR1'} = sub {
print "SIGUSER1\n";
undef @array;
$x = '!!';
};
print "$$\n";
foreach (@array) {
print "$_:\n";
sleep(2);
print "\t$x\n";
print "\t$array[$_ - 1]\n";
}
毫不奇怪,这是:
2482
1:
x
1
2:
x
2
3:
SIGUSER1
!!
Use of uninitialized value within @array in concatenation (.) or string at ./test.pl line 42.
暗示如果你在此时捕捉到信号:
my $category = # ... chose some how
处理程序中将不存在 $categoryForPid{$pid}
。等等,是的,你必须同步。