Perl question - thread/fork?

Peter Edwards peter at
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.
and CPAN

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
   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
		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";

   # parent

   # 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
   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,
   return ("", $kidpid, $runid);

Regards, Peter
Dragonstaff Limited  Business IT Consultancy

-----Original Message-----
From: at
[ at] On Behalf Of
Lee Larcombe
Sent: 09 September 2006 21:11
To: miltonkeynes-pm at
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?



Lee Larcombe
msn: leelarcombe at

MiltonKeynes-pm mailing list
MiltonKeynes-pm at

More information about the MiltonKeynes-pm mailing list