在Perl中的进程之间发送消息

时间:2014-08-29 13:18:57

标签: perl

我正在尝试使用信号实现进程之间的通信。首先,父进程启动子进程,它做一些工作,然后等待来自子进程的消息,然后再次发信号通知子进程,以便子进程继续处理等等。

我不确定实现这个的正确方法是什么,但这是我的第一次尝试:

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

然后它挂起..

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;他们把睡眠放在那里会打破信号机制。