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

Hi Monks, I'm trying to capture the PID of a child process from SYSTEM or EXEC. I have tried using FORK with EXEC which returns a PID, but not the PID listed in TaskMgr for Windows. I need to capture the PID in order to kill the process if it hangs. Here is a copy of the code I'm using to get the non-matching PID. Thanks!
#!/bin/perl use strict; use warnings; my $prog = 'some_executable'; defined( my $pid = fork ) or die "Cannot fork: $!"; print "pid:$pid\n"; unless( $pid ) { exec "$prog"; die "cannot exec date: $!"; }

Replies are listed 'Best First'.
Re: Capture PID from child process on Windows.
by BrowserUk (Patriarch) on Nov 08, 2005 at 22:11 UTC

    The problem you are encountering is that fork creates a pseudo-process (a thread) and the "pid" returned is a (negative) threadid, not a process id.

    The simplest way is to use the piped open, which spawns a real process and returns a real pid:

    perl> $pid = open KID, 'perl -e"1 while sleep 1 |' or die $!;; perl> kill 21, $pid;; Terminating on signal SIGBREAK(21) perl> close KID;;

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Capture PID from child process on Windows.
by GrandFather (Saint) on Nov 08, 2005 at 22:12 UTC

    Take a look at Win32::Spawn(COMMAND, ARGS, PID) in the Win32::Process module docs in the ActiveState documentation. Kill($exitcode) and GetExitCode($exitcode) may also be of interest.


    Perl is Huffman encoded by design.
Re: Capture PID from child process on Windows.
by antirice (Priest) on Nov 08, 2005 at 22:04 UTC
Re: Capture PID from child process on Windows.
by ikegami (Patriarch) on Nov 08, 2005 at 22:05 UTC

    Your command probably required a shell to execute, so you have the PID of the shell, the true child. Use exec PROGRAM LIST instead of exec LIST. In other words, use nothing but a (fully qualified???) file name in $prog.

    By the way, fork is not particulary strong in Windows since the non-native system call is emulated using threads. $pid = system(-1, ...) (undocumented), Win32::Process, IPC::Open2, IPC::Open3 and IPC::Run are more appropriate than fork+exec. In this case, I'd use Win32::Process unless portability is desired.

Re: Capture PID from child process on Windows.
by Amar (Sexton) on Nov 09, 2005 at 12:42 UTC
    As u need to kill the process if it hangs(meaning u need to control process), the process you create must be an asynchronous process.
    The following is a code snipet of the same under windows
    use strict; use Win32::Process; my ($processObj, $pid); Win32::Process::Create($ProcessObj, "C:\\foo\\Setup.exe", "Setup.exe", 0, NORMAL_PRIORITY_CLASS,".")|| die "$!\n"; $pid = $ProcessObj->GetProcessID();
    Using the pid you can control the process.
    To kill the process say,
    $ProcessObj->Kill($exitcode);
    Amar