【发布时间】:2012-05-15 11:09:35
【问题描述】:
我正在尝试确定从为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);
# ...
}
}
所以,%children 是从 while 循环和处理程序中访问的。这似乎没有问题:
- 不会有两个进程具有相同的
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,但我认为这也可能有问题(例如,当进行计算的子程序在总结时被中断)。
所以我的问题是:
- 我需要在这里同步吗?
顺便说一句:
- 在 perl 5.12 中是否可以嵌套调用信号处理程序,或者它们是否由解释器线性化?
更新
除了@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;
# ...
}
}
【问题讨论】:
标签: perl signal-handling