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

Dear monks!

An ill fate has landed me on Windows which I know very little about - so I hope I can find some information here.

My problem is that I want to start a new process and get a notification (asynchronously - I don't want to polly my child's status) when the child exits.

On *nix I can simply fork and will receive a SIGCHLD-signal when my child exits but on Windows fork is faked and there don't seem to be signals.

So can someone please explain to me how to do this on Windows (probably using Win32::Process instead of fork?).

Many thanks!

Replies are listed 'Best First'.
Re: child process termination on Windows
by ReturnOfThelonious (Beadle) on Nov 18, 2009 at 22:49 UTC
    You can use threads. For example:
    use strict; use warnings; use Win32::Process; use Win32; use threads; my $ProcessObj; Win32::Process::Create($ProcessObj, "C:\\windows\\system32\\calc.exe", "", 0, NORMAL_PRIORITY_CLASS, ".")|| die ErrorReport(); print "process created\n"; $| = 1; sub ErrorReport{ print Win32::FormatMessage( Win32::GetLastError() ); } sub wait_proc { $ProcessObj->Wait(INFINITE); print "process finished\n"; } my $thr = threads->create('wait_proc'); print "waiting for input\n"; $_ = <>; print "input is $_\n"; $thr->join;
    Depending on what you're doing in the main thread, the child thread could notify it (e.g. via Windows message or socket).
      Thanks, that's a good idea, but íf I want to fork a number of childs I would need one thread per child for your approach which I think is costly.
        How 'bout this:
        use strict; use warnings; use Win32::Process; use Win32::IPC 'wait_any'; use Win32; use threads; my @progs = ( 'C:\windows\system32\calc.exe', 'C:\windows\system32\notepad.exe', ); my @proclist; my %proctable; for (@progs) { my $ProcessObj; Win32::Process::Create($ProcessObj, $_, "", 0, NORMAL_PRIORITY_CLASS, ".")|| die ErrorReport(); $proctable{$ProcessObj->GetProcessID}{progname} = $_; print "process created for $_\n"; push @proclist, $ProcessObj; }; $| = 1; sub ErrorReport{ print Win32::FormatMessage( Win32::GetLastError() ); } sub wait_procs { while (@proclist) { my $x = wait_any(@proclist, INFINITE); if ($x) { my $proc = splice(@proclist, abs($x) - 1, 1); my $id = $proc->GetProcessID; my $program = $proctable{$id}{progname}; print "process finished x=$x id=$id program=$program\n"; } } print "thread exit\n"; } my $thr = threads->create('wait_procs'); print "waiting for input\n"; $_ = <>; print "input is $_\n"; $thr->join;
Re: child process termination on Windows
by cdarke (Prior) on Nov 19, 2009 at 08:28 UTC
    Yes, use Win32::Process. Signals are part of UNIX architecture and only sort-of almost work-ish on Windows (i.e. very badly).

    Win32::Process::Create sets a process object as the first parameter, and that can be used for the wait (it is documented fairly well). Here is an example:
    use Win32::Process; use Win32; my $ProcessObj; my $worked = Win32::Process::Create ( $ProcessObj, # Process object "C:\\myprog", # full path name of child program "C:\\myprog arg", # command line 0, # inherit handles boolean NORMAL_PRIORITY_CLASS, # Creation flags "."); # working directory of child die 'Error: '.Win32::GetLastError() unless $worked; # Do some stuff $ProcessObj->Wait(INFINITE); # Wait for completion my $ExitCode; $ProcessObj->GetExitCode($ExitCode) # Get child result
      Thanks - but your Wait will block the parent process until the child exits - or does it not?

      What I want is a way to have parent and child run concurrently with the parent being informed about the child exit.

        Fair enough, in that case use $ProcessObj->GetExitCode($var) which will return STILL_ACTIVE if it is,um, still active. You will need use Win32::Process qw(STILL_ACTIVE); for that.
Re: child process termination on Windows
by tokpela (Chaplain) on Nov 19, 2009 at 10:25 UTC

    I am not sure if this module will help you - but have you looked at Win32::Job

    The watch method might be able to be used to get the status of your process when it exits. But then again - this might be what you are trying to avoid - polling.