Lisa
Lisa

Reputation: 121

Killing a forked Windows process in Perl

I'd like to spawn a process, do something and kill it afterwards manually when I'm done.

It's not working though. The process starts, I see the pid and the while loop keeps running until I kill it.

Could it be, that Perl spawns a new shell which then spawns the UI process, which doesn't get killed by Perl when the shell (which Perl spawned) is killed?

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";
}

Upvotes: 0

Views: 575

Answers (1)

Borodin
Borodin

Reputation: 126722

The Forks::Super module provides many useful facilities for handling forked processes, as well as offering a more portable interface.

This program runs notepad to edit the program's own source file and kills the child process after five seconds. If you need to pass parameters to the command then you should specify it as an anonymous array of values like this. If you use a single string like cmd => qq<notepad "$0"> instead then you will start a copy of cmd.exe which in turn starts notepad.exe, and the kill command will just leave notepad running as an orphan

use strict;
use warnings;

use Forks::Super;

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

Note that if you want to apply a timeout to the child process then you can write

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

Upvotes: 1

Related Questions