Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

jjohn (22)

jjohn
  (email not shown publicly)
http://taskboy.com/
AOL IM: taskboy3000 (Add Buddy, Send Message)

Perl hack/Linux buff/OSS junkie.

Journal of jjohn (22)

Friday May 07, 2004
09:41 AM

Win32 fork() example with reaping

[ #18668 ]

Here's the deal: you're on win32, you need to fork() and you're using Perl. Since version 5.6, win32 Perl has had fork() emulation. That's good. It's emulation (accomplished at the interpreter level with threading), so standard Unix tricks like using a signal handler to reap children and control the number of child process don't work. That's bad.

Here then is my Win32 Perl recipe for the week: Limiting forked child "processes" under Win32 Perl (versions 5.6 and higher).

use strict;
use POSIX ":sys_wait_h";
use constant MAX_KIDS => 4;

my (%children, $quit) = ((), 0);
print "[$$] Entering main loop\n";
while (!$quit) {
  reap(\%children);

  if ((keys %children) <= MAX_KIDS) {
    print "[$$] Forking child $_\n";
    if (my $pid = fork()) {
      $children{$pid} = 1;
    } else {
      do_child();
      exit;
    }
  } else {
    $quit = 1;
  }

  sleep(1);
}

# reap existing kids
while (keys %children) {
  reap(\%children);
  sleep(1);
}

print "All children reaped\n";

#--------
# sub
#--------
sub reap {
  my ($kids) = @_;
  for (keys %{$kids}) {
    print "[$$]    child '$_' reapable?\n";
    next if waitpid($_,WNOHANG()) != -1;
    print "[$$]      child '$_' reaped\n";
    delete $kids->{$_};
  }
}

sub do_child {
  sleep(1) for 0..10;
  print "[$$] done\n";
}

Note that you can do other work in the main reaping loop. This is essential when that main loop is really the service state loop for a Win32 service. Also note that reaping the child "processes" isn't strictly necessary. Not only are the children not real processes (they are interpreter threads), but also no zombies can be created if the parent process exits without wait()ing for child exit codes. All child "processes" will be terminated with the parent. So you've got that going for you.

See David Roth's web site, books or articles for more excellent details on the devilish art of creating Win32 services with Perl.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • I must have spent four hours STFW'ing through the circularly referential documentation for fork(), wait(), and waitpid() before I found this article... Thanks!