ServersImproving mod_perl Driven Site's Performance -- Part VI: Forking and Executing Subprocesses...

Improving mod_perl Driven Site’s Performance — Part VI: Forking and Executing Subprocesses from mod_perl Page 7

ServerWatch content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.




Notice that exec() never returns unless it fails to start the
process. Therefore you shouldn’t put any code after exec()–it will be
not executed in the case of success. Use system() or back-ticks
instead if you want to continue doing other things in the process.
But then you probably will want to terminate the process after the
program has finished. So you will have to write:

      system "/home/httpd/perl/external.pl" or die "Cannot execute system: ";
      CORE::exit(0);

Another important nuance is that we have to close all STD* stream in
the forked process, even if the called program does that.

If the external program is written in Perl you may pass complicated
data stuctures to it using one of the methods to serialize Perl data
and then to restore it. The Storable and FreezeThaw modules come
handy. Let’s say that we have program master.pl calling program
slave.pl:

  master.pl
  ---------
  # we are within the mod_perl code
  use Storable ();
  my @params = (foo => 1, bar => 2);
  my  = Storable::freeze(@params);
  exec "./slave.pl",  or die "Cannot execute exec: ";
  slave.pl
  --------
  #!/usr/bin/perl -w
  use Storable ();
  my @params = @ARGV ? @{ Storable::thaw(shift)||[] } : ();
  # do something

As you can see, master.pl serializes the @params data structure
with Storable::freeze and passes it to slave.pl as a single
argument. slave.pl restores the it with Storable::thaw, by
shifting the first value of the ARGV array if available. The
FreezeThaw module does a very similar thing.

Starting a Short Running External Program

Sometimes you need to call an external program and you cannot continue
before this program completes its run and optionally returns some
result. In this case the fork solution doesn’t help. But we have a few
ways to execute this program. First using system():

  system "perl -e 'print 5+5'"

We believe that you will never call the perl interperter for doing
this simple calculation, but for the sake of a simple example it's
good enough.

The problem with this approach is that we cannot get the results
printed to STDOUT, and that's where back-ticks or qx() come to
help. If you use either:

  my  = 'perl -e 'print 5+5'';

or:

  my  = qx{perl -e 'print 5+5'};

the whole output of the external program will be stored in the
variable.

Of course you can use other solutions, like opening a pipe (| to
the program) if you need to submit many arguments and more evolved
solutions provided by other Perl modules like IPC::Open2 which
allows to open a process for both reading and writing.

Executing system() or exec() in the Right Way

The exec() and system() system calls behave identically in the way
they spawn a program. For example, let's use system() as an
example. Consider the following code:

  system("echo","Hi");

Perl will use the first argument as a program to execute, find
/bin/echo along the search path, invoke it directly and pass the
Hi string as an argument.

Get the Free Newsletter!

Subscribe to Daily Tech Insider for top news, trends & analysis

Latest Posts

Related Stories