2015-10-19 82 views
1

我在Windows上使用Strawberry Perl。我有一些GUI.pl应用程序运行script.pl其中运行some.exe。 perl脚本作为GUI应用程序和some.exe之间的STDIN/OUT/ERR的代理。 问题是我无法杀掉链式GUI.pl中的some.exe进程 - > script.pl - > some.exe。Perl信号处理程序和WIndows

GUI.pl发送任期script.pl

# GUI.pl 
my $pid = open my $cmd, '-|', 'script.pl'; 
sleep 1; 
kill 'TERM', $pid; 

script.pl抓 'TERM' 并试图杀死some.exe

# script.pl 
$SIG{TERM} = \&handler; 
my $pid = open my $cmd, '-|', 'some.exe'; 
sub handler { 
    kill 'TERM', $pid; 
} 

随着这个方案中,some.exe的进程继续执行。我已经了解了很多关于信号的知识,但仍不明白如何解决这个问题。

提前致谢。


而且它使用的threads的解决方案之一:

# script.pl 
use threads; 
use threads::shared; 

$SIG{BREAK} = \&handler; 

my $pid :shared; 

async { 
    $pid = open my $cmd, '-|', 'some.exe' 
}->detach; 

# 1 second for blocking opcode. After sleep handler will be applied 
sleep 1;  

sub handler { 
    kill 'TERM', $pid; 
} 

回答

0

我会警惕在Windows上使用“杀”信号的,因为他们是一个POSIX事情。 http://perldoc.perl.org/functions/kill.html

但我觉得这里的问题可能是是因为Deferred Signals。具体而言,如果您向某个流程发送信号,解释器会一直等到“安全”处理它。在“some.exe”中间不太可能。

以这种方式使用kill信号并不是特别好的IPC形式。请参阅perlmonks: Signals Vs. Windows进行一些有用的讨论。

+0

这种解释是错误的。 Windows信号不使用递延信号记录的延期过程。 – ikegami

+0

我在这个解释中发现我在IO操作期间无法处理信号。 –

0

Windows上的信号非常特殊。 INTQUIT信号比TERM更好。我对Perl和Windows如何处理信号的广泛研究总结为here

TL; DR:在Windows上,TERM可以终止Windows中的进程,但无法处理。 INTQUIT可以被处理,并且它们的默认行为是终止该过程。如果你使用Windows伪进程(这是你在Windows中调用fork时得到的结果),那么事情会变得更加复杂。

+0

'kill TERM => $ pid' [发送Ctrl-Break](http://perl5.git.perl.org/perl.git/blob/3ec400f5ce53ea1a56d283bc6bf59e75762df058:/win32/win32.c#l1258),它可以是[处理](http://perl5.git.perl.org/perl.git/blob/3ec400f5ce53ea1a56d283bc6bf59e75762df058:/win32/win32.c#l2142)。 [我无法验证这一点,因为出于某种原因我无法处理任何信号。] – ikegami