Perl question - thread/fork?

Peter Edwards peter at dragonstaff.com
Mon Sep 11 00:40:59 PDT 2006


Hi Lee, what I've done before in this situation is write a module to wrap
the spawning, monitoring and output tracking for a child process.

Parent: call routine to spawn and detach child after redirecting
input/output streams, note process id and stick it in a "process running"
SQL table; get run id back and continue with something else

Child: register an exit handler, go off and run its code

Parent: (later) call routine to check whether given run id is still active;
call routine to gain access to the standard output and standard error log
files (I use this to do the equivalent of a "tail -f" on a web screen to
check batch progress)

Child: exits; the exit handler logs the run to an a "processes complete" SQL
table and deletes the "process running" entry

Parent: (later still) calls check routine and finds child has finished; the
check routine incorporates a reaper to remove "process running" entries
where the given process ID no longer exists on the system


There's stuff in the "Perl Cookbook" which you'll find helpful.
http://www.unix.org.ua/orelly/perl/cookbook/index.htm
http://pleac.sourceforge.net/pleac_perl/processmanagementetc.html
and CPAN
http://search.cpan.org/author/GARROW/Proc-Spawn-1.03/Spawn.pm
http://search.cpan.org/author/JDB/libwin32-0.26/Job/Job.pm
http://search.cpan.org/~aristotle/Proc-Fork-0.3/lib/Proc/Fork.pm

Here's an excerpt to fork a detached child under Unix:

sub start_child
{
   # argument, locking and permission code removed for brevity
   ...

   # start child process to run command
   $SIG{CHLD} = 'IGNORE';
   my $mode = ($overwrite ? '>' : '>>' ); # overwrite or append to log
   my $kidpid = fork();
   unless (defined $kidpid)
   {
      die("can't fork: $!");
   }
   if ($kidpid == 0 ) # child
   {
		if (exists $ENV{MOD_PERL})
		{
			Apache->request->cleanup_for_exec(); # untie the
socket
		}
		setsid or warn "setsid cannot start a new session: $!";
		open STDIN, "/dev/null"			or die "Can't read
/dev/null: $!";
		open STDOUT, "$mode$logpath" or die "Can't write stdout to $
logpath: $!";
		open STDERR, "$mode$errpath" or die "Can't write stderr to
$errpath: $!";
		local $| = 1;
		print STDOUT "Started\n";
	      # run command
		exec($cmdpath); # should stop here, if not, failed to exec
		warn "could not run $cmdpath: $!";
		print "Failed could not run $cmdpath: $!\n";

	      CORE::exit(0);
   }
   # parent
   $SIG{CHLD} = 'DEFAULT';

   # catch immediate child exits, which imply the command run is invalid
   select(undef,undef,undef,1.0); 			# wait 1 second
   POSIX::waitpid(-1, POSIX::WNOHANG());	# clean up kid if its
defunct
   unless (kill(0,$kidpid))					# see if kid
has stopped
   {
	my $msg = "Child process exited quickly, possibly due to an error in
command \"$cmdpath\"";
	warn $msg;
	return ($msg, $kidpid, 0);
   }
   my $runid = sql_note_process_started($kidpid, $cmdpath, $logpath,
$errpath);
   return ("", $kidpid, $runid);
}


Regards, Peter
Dragonstaff Limited  http://www.dragonstaff.com  Business IT Consultancy

-----Original Message-----
From: miltonkeynes-pm-bounces+peter=dragonstaff.com at pm.org
[mailto:miltonkeynes-pm-bounces+peter=dragonstaff.com at pm.org] On Behalf Of
Lee Larcombe
Sent: 09 September 2006 21:11
To: miltonkeynes-pm at pm.org
Subject: Perl question - thread/fork?

Hi all

I am trying to work out how I could call a program from within a perl
script, and display some sort of indication to the user that it is running
which stops when it is finished.

So I have eg:

Print "Starting analysis. Please wait...\n";

System "programThatTakesAges";


The 'programThatTakesAges' analyses some files and can take 10,20,30 mins or
so (could be longer), then the perl script carries on and does things with
those files. I would like the user to have some feedback that something is
happening after the 'Please wait...' - a spinny cursor would be nice :-)

Anyway, I can't work out how to get the script to do the system call and
then do something whilst it waits for it to finish. I've been looking at
using a thread or a fork - I'm sure it must be one of those - but I can't
really work it out.

Anyone got any tips or example code that would help?

Thanks

Lee

============================
Lee Larcombe

www.larcombesplace.org.uk
msn: leelarcombe at hotmail.com


_______________________________________________
MiltonKeynes-pm mailing list
MiltonKeynes-pm at pm.org
http://mail.pm.org/mailman/listinfo/miltonkeynes-pm




More information about the MiltonKeynes-pm mailing list