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

I'm trying to learn the fork() command by applying it in a simple "multi-copy" command script.
It somewhat works until, I believe, it reaches the last pid. I get an error "The instruction at ####### referenced memory at #######. The memory could not be read." I don't know why. Can someone help?

Here's a snippet of the code used:
$| = 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 it +s very own @kids = (); # the child doesn't want this baggage from the par +ent last FORKER; # and we don't want the child making babies eithe +r }else{ # the parent process is returned the PID of the newborn by for +k() 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); }

regards
Sacco

Replies are listed 'Best First'.
Re: forking memory problem
by davido (Cardinal) on Nov 28, 2003 at 03:36 UTC
    You are forking within a loop. Fine, perhaps, except I don't see where the loop's upper limit ( $threads ) is being set. Is it possible that we're not seeing some important piece of code? It is pretty easy to fork-bomb a system with a runaway loop.


    Dave


    "If I had my life to live over again, I'd be a plumber." -- Albert Einstein

      davido, I don't think it is a runaway loop. If it is a run away loop, he should get error "fork didn't work: Resource temporarily unavailable", as sacco only goes to waitpid after all the fork is done.

      This has to be a Perl bug. Whatever how bad or how good sacco's code is, it is not direclty managing memory access.

        If it is a run away loop, he should get error "fork didn't work: Resource temporarily unavailable"

        I'm not going to venture a guess at this point. The error message you suggested doesn't show up in perldiag. And here is the message the original post suggested he's seeing:

        I get an error "The instruction at ####### referenced memory at #######. The memory could not be read."

        That message also doesn't appear in perldiag.

        perlbug states: Check in perldiag to see what any Perl error message(s) mean. If message isn't in perldiag, it probably isn't generated by Perl. Consult your operating system documentation instead.

        Since the OP's error message isn't listed in perldiag, I can only assume that it's either generated by a module, or by the operating system. We haven't been told what modules are in use. The original post also doesn't mention what operating system the code is running on. So we know we're not seeing a Perl error (assuming the OP gave us the correct error message), but that's about all we know for sure. The code snippet provided leaves open the possibility of a runaway loop. But it also leaves a lot of other possibilities that need clarification.

        No more guesses from me until we get more details. It's probably way premature to assume a Perl bug though. ;)


        Dave


        "If I had my life to live over again, I'd be a plumber." -- Albert Einstein
      It is being set by an argument passed to the script.
      i.e. 5
Re: forking memory problem
by Roger (Parson) on Nov 28, 2003 at 03:54 UTC
    You should always turn on use strict; in your code, especially when your code is quite complex.

    Have a look at the following loop (without use strict):
    for ($i=1;$i<=5;$i++) { print "inside loop - \$i = $i\n"; } print "outside loop - \$i = $i\n";
    What do you think the value of $i is outside the loop?

    inside loop - $i = 1 inside loop - $i = 2 inside loop - $i = 3 inside loop - $i = 4 inside loop - $i = 5 outside loop - $i = 6
    I suspect your problem is with the value of $i outside the loop.

      You should always turn on use strict; in your code, especially when your code is quite complex.

      You mean, modern Perl will segfault (because that's what the error message seems to indicate) if you don't turn on strict? Where is that documented?

      Abigail

        That was just a general comment I made about the coding style, not to do with the segfault.