in reply to Re: Learning to use fork()
in thread Learning to use fork()

Thanks for the reply. I prefer to use the fork method. My main question is what to do if the fork was not success? I still want the reports to be created even if not parallel. Let start with 5 functions:
sub1(); sub2(); sub3(); sub4(); sub5();
I would like to loop through the functions (is it even possible?) and create a fork for each one. What should I do if the fork failed?

Replies are listed 'Best First'.
Re^3: Learning to use fork()
by kroach (Pilgrim) on Jan 15, 2019 at 02:07 UTC

    Here is an example way to do what you want for educational purposes (Parallel::ForkManager is really the way to go in production code).

    It is possible to loop through functions by taking references with the \& syntax:
    sub sub1 { print 'sub1 ran' } sub sub2 { print 'sub2 ran' } my @refs = (\&sub1, \&sub2); $_->() foreach @refs;
    Fork failure is indicated by an undef return value by the fork function. If you want to go on with processing in a non-parallel manner when fork fails, you can just check if it's defined. Full example:
    use strict; use warnings; use POSIX ':sys_wait_h'; my @subs_to_run = ( \&sub1, \&sub2, \&sub3, \&sub4, \&sub5, ); foreach my $sub (@subs_to_run) { my $is_parent = fork; # try to fork next if $is_parent; # both child and fork failure will be false $sub->(); # we're in the child or fork failed, run the sub exit if defined $is_parent; # exit only if actually forked } 1 while waitpid(-1, WNOHANG) > 0; # wait for all children
      It's more clear to me now, buy it will work only if the subs does not get any arguments, right? What if they does?
      If the module you suggested can help us on solving this problem, I would love to see an example

        Parallel::ForkManager doesn't help with the code you want to parallelize. However, it can keep track of the number of forks, which you mentioned you wanted to do in the original question.

        Passing arguments is not a problem when using code references, if the aguments are determined beforehand, you can wrap them in anonymous subroutines:

        sub sub1 { print "sub1 ran, got args: [@_]\n" } sub sub2 { print "sub2 ran, got args: [@_]\n" } my @refs = ( sub { sub1(1, 2, 3) }, sub { sub1('foo', 'bar') }, sub { sub2(4, 5, 6) }, sub { sub2('some', 'string') }, ); $_->() foreach @refs;

        If you want to pass different sets of arguments to a single subroutine, you could just make an array of arguments:

        sub foo { print "Got args: [@_]\n" } my @args = ( [ 'A', 'B', 1 ], [ 'C', 'D', 2 ], ); foreach my $arg_ref (@args) { foo(@$arg_ref) }
Re^3: Learning to use fork()
by markong (Pilgrim) on Jan 15, 2019 at 10:31 UTC

    Recover or die:

    if ($pid = fork) { # parent } else { die "cannot fork: $!" unless defined $pid; # child }

Re^3: Learning to use fork()
by Anonymous Monk on Jan 15, 2019 at 09:29 UTC
    I prefer to use the fork method.

    you mean thats what your homework said you should do