Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Forking two processes in parallel

by neilwatson (Priest)
on Mar 06, 2016 at 01:10 UTC ( [id://1156902]=perlquestion: print w/replies, xml ) Need Help??

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

Greetings,

I'm trying to write a test program for an irc bot. My plan is to create a second bot, have the two bots talk to each other, and then check the results. So, I wrote some test code to start each bot and run them toether for a brief amount of time. It seems that rather than running in parallel the bots run in sequence. What have a done wrong or is there a better way?

#!/usr/bin/env perl use strict; use warnings; use Carp; fork_bot({ bot => './cfbot.pm --debug', runtime => 60 }); fork_bot({ bot => './cfbot_tester.pm', runtime => 20 }); sub fork_bot { my ( $arg ) = @_; my $pid = fork(); if ( $pid == 0 ){ exec( $arg->{bot} ) or croak "Cannot start [$arg->{bot}] [$!]"; } else{ sleep $arg->{runtime}; kill 1, $pid or croak "Cannot kill pid [$pid]"; } return; }

Neil Watson
watson-wilson.ca

Replies are listed 'Best First'.
Re: Forking two processes in parallel
by Tanktalus (Canon) on Mar 06, 2016 at 02:25 UTC

    Your fork_bot doesn't return until it has slept.

    You need to fork both off, and manage the sleep events in the parent. And the parent has to wait around for the children to finish, else the parent exiting may also terminate its children.

    Personally, I've found that using an event manager simplifies this greatly. Completely untested code:

    use strict; use warnings; use AnyEvent; use AnyEvent::Util; sub fork_bot { my $arg = shift; my $pid; my $cv = AnyEvent::Util::run_cmd( $arg->{bot}, '$$' => \$pid, ); my $w; $w = AE::timer( $arg->{runtime}, 0, sub { print "Killing $arg->{runtime} - timeout +\n"; kill INT, $pid; $w = undef; } ); $cv } my $bot1 = fork_bot({ bot => ['./cfbot.pm', '--debug'], runtime => 60 +}); my $bot2 = fork_bot({ bot => ['./cfbot_tester.pm'], runtime => 20 +}); $bot1->recv; $bot2->recv; # continue with program
    Now, I'm sure you can do this equally as well with other event handlers, or with threads. This is just what I'm used to.

    Coro can simplify this a bit further, but at this point it's not enough to warrant, IMO. (It would invert the timeout into a Coro-version of sleep, but I don't think that's a huge benefit here.)

    Also, we can use this to also clean up the $w watcher, to eliminate that timer if the child exits before the timer runs out.

    Hope that helps.

Re: Forking two processes in parallel
by andal (Hermit) on Mar 07, 2016 at 08:16 UTC

    The "fork" call starts another copy of original process. That copy continues running from exactly the same position as the parent. The only difference is the value returned from "fork". So it is obvious, that if one of those 2 processes calls "exec" and the other calls "sleep", then there's no more processes left to start one more bot. So, your second bot is started after the parent kills first bot.

    So, to really have 2 processes running independently, you have to come up with some strategy for freeing parent process. In the simplest (and ugly) case, you can use 2 forks to launch 1 bot. Something like

    sub fork_bot{ my $arg = shift; my $pid = fork(); die "Can't fork: $!\n" unless defined $pid; return if $pid != 0; $pid = fork(); die "Can't fork: $!\n" unless defined $pid; if($pid == 0){ exec($arg->{bot}) or die "Can't start $arg->{bot}: $!\n"; } sleep $arg->{runtime}; kill 1, $pid or die "Can't kill $arg->{bot}: $!\n"; exit(0); }
    Your main code, after starting bots, may do then something like
    my $chld; do{ $chld = wait(); }while($chld >= 0);
    Again, this code will work, but it is not very useful. The bots that you start this way won't be able to communicate with each other or with the parent. The style of communication (one way or both ways) shall define the complexity of the system that you have to design.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1156902]
Approved by Tanktalus
Front-paged by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (3)
As of 2024-03-29 14:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found