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

執筆者
Stas Bekman
Stas Bekman
Published: Jul 20, 2010
Updated: Nov 10, 2020
2 minute read
ServerWatch のコンテンツおよび製品のおすすめは、編集上の独立性を保っています。パートナーへのリンクをクリックすると、当社が報酬を得る場合があります。 詳細を見る



This code example will allow you to verify that indeed the spawned
child process has its own life, and its parent is free as well. Simply
issue a request that will run this script, watch that the warnings are
started to be written into the /tmp/log file and issue a complete
server stop and start. If everything is correct, the server will
successfully restart and the long term process will still be
running. You will know that it’s still running, if the warnings are
still printed into the /tmp/log file. You may need to raise the
number of warnings to do above 20, to make sure that you don’t miss
the end of the run.

If there are only 5 warnings to be printed, you should see the
following output in this file:

  started
  1
  2
  3
  4
  5
  completed

Starting a Long Running External Program

But what happens if we cannot just run a Perl code from the spawned
process and we have a compiled utility, i.e. a program written in C.
Or we have a Perl program which cannot be easily converted into a
module, and thus called as a function. Of course in this case we have
to use system(), exec(), qx() or (back ticks) to start it.

When using any of these methods and when the Taint mode is enabled,
we must at least add the following code to untaint the PATH
environment variable and delete a few other insecure environment
variables. This information can be found in the perlsec manpage.

  {'PATH'} = '/bin:/usr/bin';
  delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

Now all we have to do is to reuse the code from the previous section.

First we move the core program into the external.pl file, add the
shebang first line so the program will be executed by Perl, tell the
program to run under Taint mode (-T) and possibly enable the
warnings mode (-w) and make it executable:

  external.pl
  -----------
  #!/usr/bin/perl -Tw
  open STDIN, '/dev/null'  or die "Can't read /dev/null: ";
  open STDOUT, '>/dev/null'
      or die "Can't write to /dev/null: ";
  open STDERR, '>/tmp/log' or die "Can't write to /tmp/log: ";
  select STDERR;
  local $|=1;
  warn "startedn";
  # do something time-consuming
  sleep 1, warn "shn" for 1..20;
  warn "completedn";

Now we replace the code that moved into the external program with
exec() to call it:

  proper_fork_exec.pl
  -------------------
  use strict;
  use POSIX 'setsid';
  use Apache::SubProcess;
  {'PATH'} = '/bin:/usr/bin';
  delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
  my  = shift;
  ->send_http_header("text/html");
  {CHLD} = 'IGNORE';
  defined (my  = fork) or die "Cannot fork: n";
  if () {
    print "Parent has finished, kid's PID: n";
  } else {
      ->cleanup_for_exec(); # untie the socket
      chdir '/'                or die "Can't chdir to /: ";
      open STDIN, '/dev/null'  or die "Can't read /dev/null: ";
      open STDOUT, '>/dev/null'
          or die "Can't write to /dev/null: ";
      open STDERR, '>&STDOUT'  or die "Can't dup stdout: ";
      setsid or die "Can't start a new session: ";
      exec "/home/httpd/perl/external.pl" or die "Cannot execute exec: ";
  }
Stas Bekman

Stas Bekman is a ServerWatch contributor.

ServerWatch Logo

ServerWatch is a top resource on servers. Explore the latest news, reviews and guides for server administrators now.

TechnologyAdvice が所有・運営しています。 © 2026 TechnologyAdvice. 無断転載を禁じます

広告主に関する開示:このサイトに掲載されている製品の一部は、TechnologyAdvice が報酬を受け取っている企業のものです。この報酬は、製品がこのサイトのどこにどのように表示されるか(表示される順序など)に影響する場合があります。TechnologyAdvice は、市場で入手可能なすべての企業やすべての種類の製品を掲載しているわけではありません。