Hi Rob,

Sorry for the delay -- enjoyed the weekend away from the computer.  :-)


Rob Dixon wrote:
Raymond Wan wrote:
Rob Dixon wrote:
use strict;
use warnings;

$|++; # autoflush

$SIG{CHLD} = 'IGNORE';

my $kid = fork;

if ($kid) {
  print "in parent whose kid is $kid\n";
  sleep 10;
  my $running = kill(0, $kid);
  print "Child process ", $running ? "still running\n" : "terminated\n";
}
elsif ($kid == 0) {

  print "In child\n";

  my ($user, $system, $cuser, $csystem);

  ($user, $system, $cuser, $csystem) = times;
  printf "user: %f cuser: %f\n", $user, $cuser;

  system('myprogram') == 0 or die "myprog failed: $?";

  ($user, $system, $cuser, $csystem) = times;
  printf "user: %f cuser: %f\n", $user, $cuser;

  exit;
}
else {
  die "Cannot fork: $!\n";
}

A mixture of misunderstandings here.

- I was saying that

    $SIG{CHLD} = 'IGNORE';

  was helpful. What it does is say that the parent isn't interested in
  explicitly reaping the forked child processes and they will be reaped
  automatically when they complete. Without it they will stay active until the
  parent calls wait or waitpid.

- Once a parent process has forked it can carry on on its own while the child
  process does its thing. Only when it does a wait or waitpid is it held up
  waiting for the child. In fact what a call to 'system' does is to fork a child
  process and then immediately wait for that child to complete.

- So the simple combination of

    $SIG{CHLD} = 'IGNORE';
    my $kid = fork;

    if (not defined $kid) {
      warn "Unable to fork";
    }
    elsif ($kid == 0) {
      system('myprogram') == 0 or die "myprog failed: $?";
    }

  starts a child process that doesn't need reaping when it completes, and leaves
  the parent process free to continue executing. At least that is what is
  supposed to happen but wouldn't work on Windows.

And by the way, a child process doesn't actually get a /copy/ of the
interpreter: it simply has the same copy mapped at the same place in its address
space. In general this is true of any read-only segments, and it is only the
variable data space that must be duplicated so that a child process can execute
independently of its parent. Even so you should not make your program
unnecessarily complex, and I believe the code above does what you want. There
isn't even a need for any action on the parent side of the fork (child process
ID is non-zero).



Thanks for your help! I got it working now...all seems ok. And yes, there was a misunderstanding on my part; thank you for making it all clear now -- even about what the child process is/does.

Am I correct by saying that your code above forks a child and then the child forks another child (via the system command). My code (in pseudo-form) now looks like this:

$SIG{CHLD} = 'IGNORE';
my $kid = fork;

if (!defined $kid) {
 warn "Cannot fork: $!\n";
}
elsif ($kid == 0) {
 $SIG{CHLD} = 'DEFAULT';
 setsid () or die "Can't start a new session: $!";

## Re-direct filehandles to /dev/null so that they don't go to the same place as the
 ##  parent process

 my $result = system ($cmd);
 ##  Test $result's value

 ##  print the time by first using the "times" command

 ##  Need to exit or else we will load the web page
CORE::exit (0); }


I don't entirely know whether or not I need the "setsid" command. I don't understand explanations of the command, but it was suggested on a web page and having it in doesn't seem to do anything bad.

I did realize I need the second SIG{CHILD} because otherwise, I get an error from the "system" command and a user time (child) of 0 seconds. I presume the child process needs to wait for "system" to return. I also need the final exit because otherwise, there would be two processes loading up the web page (the next file in the sequence).

I think this is right now...seems to be the minimum to get things working. I presume if I removed the "fork" and second "SIG{CHILD}", I can replace "system" with "exec". Perhaps its the same thing?

I did notice when I ran it that occasionally, the number of apache processes goes up...but this wasn't consistent (i.e., every time I ran this program). So, I think this has to do with apache's process management and when it thinks it is necessary to have more processes to manage the load...

Thanks again, Rob!  Quite happy it seems to work now...

Ray



--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/


Reply via email to