1

I'm new to fork concept. I'm trying a simple script with fork loop expecting to execute twice but end up with 3 occurrence. is it because i did not exit the child process ? can you clarify please

script :

#!/usr/bin/perl

open(my $fh, '>', 'report.txt');
print $fh "before invoke fork \n";
close $fh;

@list = (1, 2);

foreach $a (@list){

    if($pid = fork){
       open(my $fh, '>>', 'report.txt');
       print $fh "Parent process! $a $pid\n";
       close $fh;

    }else {
       open(my $fh, '>>', 'report.txt');
       print $fh "Child process $a $pid\n";
       close $fh;
    }
}

output:

before invoke fork My second report generated by perl 1 1808 My second report generated by perl 2 1809 My thrid report generated by perl 2 0 My thrid report generated by perl 1 0 My second report generated by perl 2 1810 My thrid report generated by perl 2 0

Mayur
  • 13
  • 4
  • 1
    After the `if-else` both parent and child continue, so they both go for the second iteration. During which you fork again. Print something (to screen) right after `foreach`. – zdim Oct 22 '16 at 09:53
  • A comment. This is fun and useful. But it comes with things that one must know (ang with gotchas) and I suggest careful study of literature along with play. Some sources: [fork](http://perldoc.perl.org/functions/fork.html), [exec](http://perldoc.perl.org/functions/exec.html), [wait](http://perldoc.perl.org/functions/wait.html), [waitpid](http://perldoc.perl.org/functions/waitpid.html), and (at least some of) [perlipc](http://perldoc.perl.org/perlipc.html). Then Perl Cookbook, supposedly "outdated" but also really not -- with _plenty_ of crucial information. And then there are many modules. – zdim Oct 23 '16 at 02:19

2 Answers2

2

It's because the point at which you fork() both processes start at exactly the same point.

So 'child 1' will continue to run, and continue through the loop, and run 'iteration 2'.

So parent will fork twice, child 1 will fork once, and child 2 - because it's the last loop iteration - will not fork at all.

I would suggest you really should consider Parallel::ForkManager because it simplifies this a lot. And also - turn on use strict; and use warnings. And don't use single letter variables, especially not $a.

Here's some example code of how to use Parallel::ForkManager.

However to address your problem - sticking a last in the child stanza will cause it to bail out of the loop.

Community
  • 1
  • 1
Sobrique
  • 52,974
  • 7
  • 60
  • 101
1

You are not waiting child process in your loop. There is an good explanation about fork in loops here:

http://perlmaven.com/fork

There is a manual too.

http://perldoc.perl.org/perlfork.html

Try to be careful about all possibilities in a fork. Treat problems matters! A simple, good and recommended way to implement:

use strict;
use warning;
use Carp qw/confess/;
my $pid = fork;

if(!defined($pid)){
  confess "\nWhy you hates me, O.S.? Why?\nANSWER: $!\n\n";
}
elsif($pid == 0){
  #Child process. Do something and exit
}
else{
  #Parent process
  waitpid $pid,0; 
}

There is another features related that is not described in this example. To read more about it, please checkout the manual linked above

Checkout Parallel::ForkManager too!

Andre Carneiro
  • 708
  • 1
  • 5
  • 27