Be sure and wait against your sub processes.  When they’re done, that will ensure they clear.  Disclaimer: I cut this out of something I wrote and cleaned it up for consumption so I may have missed something here and there in the cleanup.

 

Something like this:

 

foreach $Something ($Somelist)

  {

if (scalar(keys %PidList) < $Parms{MaxThreads})

     {

 

            print  "Creating a thread for $Something\n”;

 

            if ($ForkResult=fork)

               {

                 print "Adding $ForkResult to thread tracking list\n";

                 #Keep the PID to track

                 $PidList{$ForkResult}=$Something;

               } elsif (defined $ForkResult)

               {

                 #We're the child

                 print "Childthread: Thread is executing a process $Something\n";

                 &Process; -----àcall some subroutine you want to do.

                 exit;

               }else

               {

                 &Mainlog ("Unknown error forking: $! $^E","FATAL");

               }

 

     } else

     {

            print "Maximum copy operations in progress ($Parms{MaxThreads}) - waiting 5 seconds for some to complete\n";

            # We have the maximum number of processes executing - wait for interval then try again.

            sleep 5;

 

            # Wait against the children

            &WaitCopies;

 

            #Look again to see if we can start more copies

            redo Begin;

     }

 

}

 

print "No more pending copy operations queued - waiting for completion of operations in progress\n";

 

# Wait on all the executing processes

while (scalar (keys %PidList) != 0 )

  {

print "Waiting for copies to complete: ",scalar (keys %PidList)," in progress\n";

        sleep 5;

        &WaitCopies;

      

  }

 

# We’re done

 

sub WaitCopies

  {

    foreach $Process (keys %PidList)

            {

 

              $Result = waitpid( $Process, &POSIX::WNOHANG );

               if ($Result==-1) {

              $Result = waitpid( $Process, &POSIX::WNOHANG );

              print "Process $Process ($PidList{$Process}) complete\n";

              delete $PidList{$Process};

                } else

            {

                print "Process $Process ($PidList{$Process}) still active\n";

            }

            }

}

 

-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]]
Sent
: Thursday, September 26, 2002 11:56 AM
To: [EMAIL PROTECTED]
Subject: Win32::Job/Process - maintaining constant number of sub-processes

 

Hi all,

 

I'd really appreciate any help with a problem I am having.

 

I am trying to achieve the following basic logic in Perl on W2k Server...

 

·         When it starts, my script spawns a pre-defined number (10) of identical sub-processes

·         It then continuously loops back every few seconds to check if any have completed

·         If a processes has completed, it spawns another instance to replace it

·         And so on

 

I have tried using Win32::Process and that works well, but when the script terminates the sub-processes continue to run (detatched).

 

Reading the documentation it seems to me that Win32:Job is more suitable my rough attempt at coding (below) is even worse that the version using Win32::Process - it does what is described above using the "watch" method to keep an eye on the spawned processes and starting new ones as required.

 

But the problem is, when the last of the 10 originally spawned processes exits, the entire script exits and all the sub-processes die with it rather than continuing to spawning new processes until I decide for some arbitrary reason to exit and kill the entire process tree.

 

Has anybody got any pointers as to how I can add new processes to a Win32::Job structure and have them included in the "watch" method?

 

Thanks.

 

Barry Caruth.

 

--- code starts here ---

 

use strict;

use warnings;

use Win32::Job;

 

# Use sleep.exe from resource kit to hide complexity of real process

our $exe_path = "c:\\program files\\resource kit\\sleep.exe";

 

our $count = 0;

my $return = 0;

our %pid_hash = ();

 

our $job = Win32::Job->new or die $!;

 

while( $count < 10 ) # Max number of threads

{

      &start_process;

      $count++;

};

 

while ($return == 0) {

      sleep 2;

      $return = $job->watch(\&handler,2,1);

};

 

print "done\n";

 

 

sub start_process {

 

      my $pid;

      $pid = $job->spawn( $exe_path, "sleep " . (5 * ($count+1))) or die $!;

      $pid_hash{$pid} = "";

      print "Process $pid Started\n";    

     

};

 

sub handler {

 

      my $status;

      my $pid;

      my $value;

      my $exitcode = 0;

     

      $status = $job->status();

     

      foreach $pid (keys %$status) {

            $exitcode = $$status{$pid}{exitcode};

           

            if ($exitcode != 259) {

                  if (exists $pid_hash{$pid}) {

                        print "Process $pid Finished : $exitcode\n";

                        delete $pid_hash{$pid};

                        &start_process;

                  };

            };

 

      };

 

      return 0;

     

};

 

Reply via email to