Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm working on a script which forks a child process. I have done modifications for the parent to monitor the child. On maximum timeout I'm killing the child process. The issue is I'm running an exe from the child which doesn't die on kill the child. I tried to explicitly kill the process with taskkill on windows and it works fine. But I face portability issues because of using taskkill. Can anybody help on this?
overview:
$pid = fork; # Fork error if ( !defined($pid) ) { print "ERROR: fork()\n"; exit; } elsif ( $pid == 0 ) { exec('C:\WINNT\system32\calc.exe'); exit; } else { # Parent process # Monitors the child process for maximum timeout # on timeout kill 9,$pid; exit; }
On timeout I tried killing the child proces but the exe is still alive.I have two questions here: 1) Is there any way I can access the pid of the exe (called from the child process) from the parent process? Reason: I tried Win32::Proc but the obj handle was not visible to the parent. I had the same issue while using pipes. 2) Is there a better way to monitor the child process? Restriction: I'm forced to use only the standard modules and hence unable to download and use CPAN modules. I'd appreciate any help on the issue.

Replies are listed 'Best First'.
Re: kill a process with process name
by BrowserUk (Patriarch) on Apr 13, 2010 at 13:09 UTC

    Don't use fork on Windows. Windows emulates fork using a thread. Therefore, exec cannot replace the "child process" with the program exec'd. Therefore the "$pid" for the child does not refer to that exec'd process, but rather is actually a thread handle. So killing that "$pid", only kills the thread, and not the exec'd program.

    A far simpler mechanism of running an asynchronous process on windows is to use system with a first parameter of '1'. It will the return the pid of the program started and kill will act on it directly:

    perl -wle"my $pid= system 1,'c:/windows/system32/calc.exe';sleep 3;kil +l 9,$pid"

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      The actual script uses cmd in backticks `command 2>&1 >NUL` instead of exec. While replacing with system do I need to take care of anything?

        No. As you are redirecting all output to the nul device, you woudl have been better using system anyway. Backticks is only for when you want to retrieve the output.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: kill a process with process name
by cdarke (Prior) on Apr 13, 2010 at 16:15 UTC
    I tried Win32::Proc but the obj handle was not visible to the parent

    This works for me:
    use warnings; use strict; use Win32::Process; my $ProcessObj; Win32::Process::Create ( $ProcessObj, # Process handle "C:\\Perl\\bin\\perl.exe", "C:\\Perl\\bin\\perl.exe gash1.pl", 0, # inherit handles boolean NORMAL_PRIORITY_CLASS, # Creation flags "."); my $pid = $ProcessObj->GetProcessID(); my $exitcode = 37; print "Hit <RETURN> to continue...."; <STDIN>; Win32::Process::KillProcess($pid, $exitcode);
    gash1.pl:
    use warnings; use strict; while (1) { print "$0 in a loop....\n"; sleep 1; }
    I had a similar requirement a while ago, Proc::Background does a similar thing, but I also had to use standard modules. I have put my code on my scratchpad - feel free to use any bits you like.
      thanks but I'm using fork hence the handle is not visible to the parent process.