$| = 1; # turn off buffering my $pid = $$; # $$ holds the current process ID number my $parent = 0; # the original process was an immaculate conception my @kids = (); # no babies yet FORKER: for ($i = 1; $i <= $threads; $i++){ my $newpid = fork(); if ( not defined $newpid ){ # if return value of fork() is undef, something went wrong die "fork didn't work: $!\n"; }elsif ( $newpid == 0 ){ # if return value is 0, this is the child process $parent = $pid; # which has a parent called $pid $pid = $$; # and which will have a new process ID number of its very own @kids = (); # the child doesn't want this baggage from the parent last FORKER; # and we don't want the child making babies either }else{ # the parent process is returned the PID of the newborn by fork() logentry("$$ spawned $newpid",$log_file); push @kids, $newpid; } } if ( $parent ){ # if I have a parent, i.e. if I'm the child process do_something(); exit( 0 ); }else{ # parent process needs to preside over the death of its kids while ( my $kid = shift @kids ){ logentry("Parent waiting for $kid to die",$log_file); my $reaped = waitpid( $kid, 0 ); unless ( $reaped == $kid ){ logentry("Something's up: $?",$log_file); } } } sub do_something { $offset = 0; if ($i == $threads){ $offset = $num_of_files - ($threads*$per_batch); } $start_point = (($i-1)*$per_batch)+1; $end_point = $i*$per_batch + $offset; for ($ii = $start_point; $ii <= $end_point; $ii++) { if (!$testmode){ copy "$list[$ii-1]" => "$target"; } logentry("copying $list[$ii-1] => $target",$log_file); } return(1); }