【问题标题】:Killing a forked Windows process in Perl在 Perl 中杀死一个分叉的 Windows 进程
【发布时间】:2015-04-24 11:41:05
【问题描述】:

我想生成一个进程,做一些事情,然后在我完成后手动终止它。

但它不起作用。进程开始,我看到 pid 和 while 循环一直运行,直到我杀死它。

难道 Perl 会产生一个新的 shell,然后它会产生 UI 进程,当 shell(Perl 产生的)被杀死时,它不会被 Perl 杀死?

my $cmd = "notepad.exe";
my $sleepTime = 10;#60 * 10;

$childPid = fork(); 
if ($childPid)
{ # Parent
  print "Started child process id: $childPid\n";
  sleep $sleepTime;

  $SIG{CHLD} = 'IGNORE';
  while (kill(15, $childPid))
  {
    my $numKilled = kill(SIGTERM, $childPid);
    printf("numKilled: %s\n", $numKilled);
    printf("numKilled: %s\n", $childPid);
    sleep 1;
  }
}

elsif ($childPid == 0)
{ # Child
  system($cmd);
  exit 0;  # will never get here
}
else
{ # Unable to fork
  die "ERROR: Could not fork new process: $!\n\n";
}

【问题讨论】:

  • 鉴于您的子进程是notepad.exe,我猜您使用的是 Windows。如果是这样,您可能需要明确提及这一点,因为 Windows 上的进程管理可能与典型地与 Perl 相关联的 *nix 环境中有所不同。
  • 如果 $childPidundef$childPid == 0 将评估为 true 并在您启用警告时引发 Use of uninitialized value $childPid in numeric eq (==) 警告。这意味着最终的else 子句将永远不会被执行。你应该改用elsif ( defined $childPid )
  • fork 和信号都是在 Windows 上由 Perl 模拟的 unix 概念。这可能不是最好的方法。你考虑过使用 Win32::Process 吗?

标签: windows multithreading perl fork kill


【解决方案1】:

Forks::Super 模块为处理分叉进程提供了许多有用的工具,并提供了更便携的界面。

这个程序运行notepad来编辑程序自己的源文件,并在五秒后杀死子进程。如果您需要将参数传递给命令,那么您应该将其指定为像这样的匿名值数组。如果您使用像 cmd => qq<notepad "$0"> 这样的单个字符串,那么您将启动 cmd.exe 的副本,然后启动 notepad.exe,而 kill 命令只会让记事本作为孤儿运行

use strict;
use warnings;

use Forks::Super;

if ( my $pid = fork({ cmd => [ 'notepad', $0 ] }) ) {
  sleep 5;
  Forks::Super::kill('TERM', $pid);
  print "Killed\n";
}

请注意,如果您想对子进程应用超时,那么您可以编写

my $pid = fork({ cmd => 'notepad', timeout => 600 })

【讨论】:

    猜你喜欢
    • 2018-08-05
    • 2018-08-28
    • 2019-06-14
    • 1970-01-01
    • 2017-07-17
    • 2016-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多