Perl - 子进程向父进程发出信号

3

我编写了以下代码来测试子进程和父进程之间的信号传递。理想情况下,当子进程向父进程发送SIGINT时,父进程应该在新迭代中返回并等待用户输入。我观察到在perl 5.8中可以实现这一点,但是在perl 5.6.1中(我被要求使用),父进程实际上会被“杀死”。没有下一个迭代。

my $parent_pid = $$;
$pid = fork();
if($pid == 0)
{   
    print "child started\n";
    kill 2, $parent_pid;
}
else
{
    while(1)
    {
        eval
        {
            $SIG{INT} = sub{die "GOTCHA";};
            print 'inside parent'."\n";
            $a = <>;
        };
        if($@)
        {
                print "got the signal!!!!\n$@\n";
                next;
        }
    }

}

有人能否提供解决这个问题的方法或其他方式,以便向父级发送信号,使其进入新迭代。


抱歉,无法重现。 - int2000
1
Windows系统中既没有fork也没有信号(signals)的概念,这些都是Unix的概念。Perl语言模拟了它们,你所遇到的问题就是由于此造成的。 - ikegami
是的,在Windows上,使用较新版本的Perl可以更好地模拟fork()和信号。您可能希望直接从Win32::IPC使用Windows同步对象。 - Alex
2个回答

3

造成5.6.X版本失败的原因可能是Perl旧时处理信号的方式,这个问题在Perl 5.8.0版本中通过'安全信号处理'得到了解决。无论如何,您正在使用实际上已经过时的Perl版本,应该向您的上级强烈建议至少升级到Perl 5.12版本,最好是5.14版本。


2
这很可能是一种竞态条件,由子进程在父进程准备好之前发送SIGINT引起的。请记住,在fork()后,您将拥有两个独立的进程,每个进程可以按其喜欢的速度进行操作。
在您的情况下,最好在fork()调用之前设置SIGINT处理程序,以确保在子进程尝试kill()其父进程之前它已经准备就绪。
(稍作更正):
$SIG{INT} = sub { die "GOTCHA" };

my $parent_pid = $$;
defined( my $pid = fork() ) or die "Cannot fork() - $!";

if($pid == 0)
{   
    print "child started\n";
    kill INT => $parent_pid;
}
else
{
    while(1)
    {
        eval
        {
            print "inside parent\n";
            <>;
        };
        if($@)
        {
            print "got the signal!!!!\n$@\n";
            next;
        }
    }
}

在尝试不同的事情时,我通过适当使用“sleeps”来确保没有竞态条件。无论如何,那可能就是原因。 - Siddharth Gaur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接