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";
>> }
> 
> Yes, I am running this on a Linux system.  So, as I said, this is 
> running under modperl/mason for a web server.  What I want to do is to 
> start off a running C++ program and have the main process immediately 
> come back and show something to the user.  That is the reason why I have 
> that line there in the first place.  Yes, without it, the child would be 
> reaped, but the downside is that the main process is (I think) going to 
> wait for the C++ program to run...and I don't want that.  Especially 
> since in a web server setting, I guess the client will just see that a 
> web page is trying to load and almost certainly will click "Reload" 
> uncontrollably...  :-)
>
> That is why I want the child process to be detached.  Wanting that 
> causes them to be zombies, so then the problem gets bigger and bigger.
>
> To be honest, I started by searching for "modperl" and "starting a 
> process" on the web and found some lines of code resembling what I first 
> posted and have since been modifying that.  I haven't taken a long, hard 
> look at each individual line to see if it is correct or not applicable 
> for my problem.  (No code I have found on the Net has addressed the 
> issue of timing that process, though.)
> 
> Thanks for the source code!  I'll play with it; someone I am working 
> with also proposed something similar just yesterday...obviously, my 
> double-forking is raising eyebrows, so I should take a good look at what 
> I am doing. 
> 
> Actually, the double-forking does work...I got it working a couple of 
> days ago.  But, I'm new to modperl, and I think a fork doesn't copy the 
> perl interpreter, but a copy of the whole apache process...so, yes, a 
> single fork is going to be a performance hit, so one is better than 2, 
> if I can get away with it...  Thanks a lot!

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).

HTH,

Rob

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


Reply via email to