views:

1452

answers:

5

I would like to call other Perl scripts in order to perform a contention test from with a main Perl script.

Something like this currently works:

system("perl 1.pl");
system("perl 2.pl");
exit;

However, I would like to kick these off as independent threads running at the same time.

I tried, based on my Google searches, doing something like this:

system(1, "perl 1.pl");
system(1, "perl 2.pl");
exit;

That doesn't work. The main script exists immediately, which is fine, but the underlying threads I want to spawn don't get kicked off. I was wondering if there was something else I have to do or if anyone else has done something like this.

Thanks for any help in advance.

+10  A: 
use threads;
$thr1 = threads->create('msc', 'perl 1.pl');
$thr2 = threads->create('msc', 'perl 2.pl');

$thr1->join();
$thr2->join();

sub msc{ ## make system call
  system( @_ );
}

This will wait for both to finish executing before the it will exit. I'm guessing this is what you want from your original question, right? If not feel free to drop a comment and edit your post to explain it better, and I'll try again.

scragar
You should really use `$^X` instead of counting on `perl` being in the PATH.
Chas. Owens
It's not to hard to divine from context, but I looked up $^X: under use English it is $EXECUTABLE_NAME - "The name used to execute the current copy of Perl"
Drew Stephens
+2  A: 

Use the fork command to do this, or do it from a shell script. The shell script (unix only) would look something like:

nohup perl 1.pl &
nohup perl 2.pl &
exit

And the perl command would look like:

if ( ! fork() )
{
    system("perl 1.pl");
}
if ( ! fork() )
{
    system("perl 2.pl");
}

There are better ways to do this, meaning write the contention in one script using perl, but this will work. Make sure that in your parent script you add in a SIG_CHLD function with wait() in it. You can find more on this kind of event handling out there. While system("perl 1.pl &"); might work (I haven't tested it), I think that forking and waiting is too valuable a resource not to mention.

Horus
For more information: http://search.cpan.org/dist/perl/pod/perlipc.pod
Horus
This assumes you're on a platform that supports nohup...
Kev
You might as well fork then exec.
brian d foy
A: 

Horus's code will need to exit after invoking system() or else the 2.pl script will get run twice. Also use wait if you don't want the program to end until the system calls are finished.

if ( ! fork() ) {
    system("perl 1.pl");
    exit 0;
}
if ( ! fork() ) {
    system("perl 2.pl");
    exit 0;
}
1 while wait > -1;
mobrule
You need to check the return of `fork`. If it returns `undef` (which is also false) then the `fork` failed.
Chas. Owens
You might as well exec after the fork and save yourself a process.
brian d foy
+1  A: 

Have a look at Parallel::ForkManager on CPAN - provides a neater interface to threading, which should do exactly what you're looking to do ;)

robbiebow
+3  A: 

You can fork off processes to run the commands for you. If you do, you will probably want to use exec instead of system:

#!/usr/bin/perl

use strict;
use warnings;

die "could not fork: $!" unless defined (my $first_pid = fork);

#first child
exec $^X, "1.pl" unless $first_pid;

die "could not fork: $!" unless defined (my $second_pid = fork);

#second child
exec $^X, "2.pl" unless $second_pid;

waitpid $first_pid,  0;  #wait for first child to finish
waitpid $second_pid, 0;  #wait for second child to finish

See also: $^X and waitpid

Chas. Owens