Servers Improving 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 4




The simplest solution is to ignore your dead children. Just add this
line before the fork() call:

  {CHLD} = 'IGNORE';

When you set the CHLD (SIGCHLD in C) signal handler to
'IGNORE', all the processes will be collected by the init process
and are therefore prevented from becoming zombies. This doesn't work
everywhere, however. It proved to work at least on Linux OS.

Note that you cannot localize this setting with local(). If you
do, it won't have the desired effect.

So now the code would look like this:

  my  = shift;
  ->send_http_header('text/plain');

  {CHLD} = 'IGNORE';

  defined (my  = fork) or die "Cannot fork: n";
  if () {
    print "Parent has finishedn";
  } else {
      # do something time-consuming
      CORE::exit(0);
  }

Note that waitpid() call has gone. The {CHLD} = 'IGNORE';
statement protects us from zombies, as explained above.

Another, more portable, but slightly more expensive solution is to use
a double fork approach.

  my  = shift;
  ->send_http_header('text/plain');

  defined (my  = fork) or die "Cannot fork: n";
  if () {
    waitpid(,0);
  } else {
    defined (my  = fork) or die "Kid cannot fork: n";
    if () {
      CORE::exit(0);
    } else {
      # code here
      # do something long lasting
      CORE::exit(0);
    }
  }

Grandkid becomes a ''child of init'', i.e. the child of the process
whose PID is 1.

Note that the previous two solutions do allow you to know the exit
status of the process, but in my example I didn't care about it.

Another solution is to use a different SIGCHLD handler:

  use POSIX 'WNOHANG';
  {CHLD} = sub { while( waitpid(-1,WNOHANG)>0 ) {} };

Which is useful when you fork() more than one process. The handler
could call wait() as well, but for a variety of reasons involving the
handling of stopped processes and the rare event in which two children
exit at nearly the same moment, the best technique is to call
waitpid() in a tight loop with a first argument of -1 and a second
argument of WNOHANG. Together these arguments tell waitpid() to
reap the next child that's available, and prevent the call from
blocking if there happens to be no child ready for reaping. The
handler will loop until waitpid() returns a negative number or zero,
indicating that no more reapable children remain.

While you test and debug your code that uses one of the above
examples, You might want to write some debug information to the
error_log file so you know what happens.

Read perlipc manpage for more information about signal handlers.

A Complete Fork Example

Now let's put all the bits of code together and show a well written
fork code that solves all the problems discussed so far. I will use an
script for this purpose:

Latest Posts

KVM vs VMware Hypervisor Comparison 2020

The KVM vs VMware hypervisor comparison is a classic debate. Hypervisors have increased in usability and power over the last several years as more...

Compare HP’s iLo & Dell’s iDRAC Server Management Tools

Most servers shipped from the major manufacturers today come with some type of out-of-band management tool or baseboard management controller (BMC). Two of the...

Get-MsolUser PowerShell Attributes & Properties

This article has been updated for 2020. Please note that WAAD was retired in 2018, but the cmdlets listed in this article are still...

Microsoft Azure PowerShell Scripts and Commands

Using PowerShell scripts and commands for quickly executing tasks in Windows operating systems offers a number of benefits over traditional scripting languages, such as...

Microsoft Hyper V Review

Microsoft Hyper-V: The Bottom line Microsoft Hyper-V lagged behind VMware's virtualization tool, one of the most popular tools in the space, when it was first...

Related Stories