我正在尝试使用信号实现进程之间的通信。首先,父进程启动子进程,它做一些工作,然后等待来自子进程的消息,然后再次发信号通知子进程,以便子进程继续处理等等。
我不确定实现这个的正确方法是什么,但这是我的第一次尝试:
use warnings;
use strict;
use feature qw(say);
my $forever=1000000;
my $parPID=$$;
my $child = fork();
if( $child == 0 ){
runSubProc($parPID,$forever);
}
$SIG{"USR1"}=sub {
say "Parent: got signal 1";
$SIG{"USR1"}=sub {
say "Parent: got signal 2";
exit 0;
};
sleep 5;
kill 'USR1', $child;
sleep $forever;
};
say "Waiting for child processes..";
sleep $forever;
sub runSubProc {
my ($parPID,$forever)=@_;
$SIG{"USR1"}=sub {
say "Child: got signal 1";
$SIG{"USR1"}=sub {
say "Child: got signal 2";
exit 0;
};
sleep 7;
kill 'USR1', $parPID;
sleep $forever;
};
sleep 5;
kill 'USR1', $parPID;
sleep $forever;
}
这不起作用,输出为:
Waiting for child processes..
Parent: got signal 1
Child: got signal 1
然后它挂起..
答案 0 :(得分:6)
根本原因是信号处理程序中的sleep $forever
。因为您的流程已经处理' SIGUSR1'下一个终止信号没有被处理 - 这是为了避免信号中断信号的各种肮脏。避免在处理程序中阻止的任何内容。
这似乎有效:
$SIG{'USR1'} = \&handle_USR1;
my $ppid = $$;
my $child_pid = fork();
sub handle_USR1 {
if ( $signalled++ ) { print "$$: got second USR1\n"; exit 0 }
print "$$: caught SIGUSR1\n";
if ( not $child_pid ) {
print "$$: Child got a SIGUSR1\n";
sleep 7;
print "$$: (child) sending signal to $ppid\n";
kill 'USR1', $ppid;
} else {
print "$$: (parent) got USR1\n";
sleep 5;
print "$$: parent signalling child\n";
kill 'USR1', $child_pid;
}
}
if ($child_pid) {
print "$$ ( parent ) waiting\n";
sleep 500;
} else {
print "$$: (child) waiting\n";
sleep 5;
print "$$: Child signalling $ppid\n";
kill 'USR1', $ppid;
sleep 500;
}
您可能需要稍微重新洗牌,但核心要点是 - 动态重新定义您的信号处理程序,尤其是“拖延”#39;他们把睡眠放在那里会打破信号机制。