You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Oliver Frommel <of...@linuxnewmedia.de> on 2010/11/12 11:42:51 UTC

Forking in postconfig stage

Hi there,

I'd like to know if it's possible to fork an infinite loop in the postconfig stage of the Apache lifecycle. I am trying to do it in a file that I 'use' in the startup.pl that in turn is called by PerlPostConfigRequire. The fork code I am using is almost the same as the "Complete fork example" from the book, however I had to remove all references to the Apache request $r because it is not available at this stage. In the child process I am creating data that is exposed to other requests via IPC::Shareable, but the requests just seem to hang. 

The code looks like this:

startup.pl:
...
  use Datastore::Cache ( );
...

Datastore/Cache.pm:
...
  if ($kid) {
    ...
  } else {
      tie $H, 'IPC::Shareable', 'Test', {create => 1, mode => 0666};

      while(1) {
        my $rnd = rand(5);
        $H = $rnd;
        sleep(60);
      }
  }


As you can see, the general problem I am trying to solve is the global creation of some data that is subject to global change (not dependent on requests) but is available to all requests on a specific URL. Maybe there better ways of achieving my general goal than forking?

Thanks for your help
Oliver


Re: Forking in postconfig stage

Posted by Oliver Frommel <of...@linuxnewmedia.de>.
> The fork is certainly not the problem.
> 
> ...

I didn't understand all of your code but got it to work with some
modifications (for instance "POSIX::_exit(0)"), so thanks for your help.

Unfortunately after all my solution was slower than the PHP thing I
wanted to substitute, although I was trying out your IPC::Scoreboard and
IPC::Shareable.

Best
Oliver

Re: Forking in postconfig stage

Posted by Torsten Förtsch <to...@gmx.net>.
On Friday, November 12, 2010 11:42:51 Oliver Frommel wrote:
> I'd like to know if it's possible to fork an infinite loop in the
> postconfig stage of the Apache lifecycle. I am trying to do it in a file
> that I 'use' in the startup.pl that in turn is called by
> PerlPostConfigRequire. The fork code I am using is almost the same as the
> "Complete fork example" from the book, however I had to remove all
> references to the Apache request $r because it is not available at this
> stage. In the child process I am creating data that is exposed to other
> requests via IPC::Shareable, but the requests just seem to hang. 
> 
> The code looks like this:
> 
> startup.pl:
> ...
>   use Datastore::Cache ( );
> ...
> 
> Datastore/Cache.pm:
> ...
>   if ($kid) {
>     ...
>   } else {
>       tie $H, 'IPC::Shareable', 'Test', {create => 1, mode => 0666};
> 
>       while(1) {
>         my $rnd = rand(5);
>         $H = $rnd;
>         sleep(60);
>       }
>   }
> 
> 
> As you can see, the general problem I am trying to solve is the global
> creation of some data that is subject to global change (not dependent on
> requests) but is available to all requests on a specific URL. Maybe there
> better ways of achieving my general goal than forking?

The fork is certainly not the problem.

<Perl>
sub My::PostConfig {
  use IPC::ScoreBoard;
  use Apache2::ServerUtil ();
  if( Apache2::ServerUtil::restart_count>=2 ) {
    $My::sb=SB::anon 0, 0, 3;
    my $pid;
    select undef, undef, undef, 0.1 until defined($pid=fork);
    unless($pid) {
      SB::set_extra $My::sb, 2, $$;	# PID
      SB::set_extra $My::sb, 1, 1;	# running
      while( SB::get_extra $My::sb, 1 ) {
        SB::set_extra $My::sb, 0, int rand 0x7fffffff;	# value
        sleep 1;
      }
      SB::set_extra $My::sb, 2, 0;	# PID
      require POSIX;
      POSIX::_exit 0;
      kill 'KILL', $$;		# just in case _exit() fails
    }
  }
  0;
}

sub My::Reponse {
  use Apache2::RequestRec ();
  use Apache2::RequestIO ();
  my ($r)=@_;
  my @l=SB::get_all_extra $My::sb;
  SB::set_extra $My::sb, 1, 0 if $r->args eq 'stop';
  $r->content_type('text/plain');
  $r->print("value=$l[0], running=$l[1], pid=$l[2]\n");
  0;
}
</Perl>
PerlPostConfigHandler My::PostConfig
<Location /test>
  SetHandler modperl
  PerlResponseHandler My::Response
</Location>

$ curl http://localhost/test
value=380451520, running=1, pid=6265
$ curl http://localhost/test
value=1301930535, running=1, pid=6265
$ curl http://localhost/test?stop
value=1285288548, running=1, pid=6265
$ curl http://localhost/test
value=1285288548, running=0, pid=0

I don't have IPC::Shareable here. So I took IPC::ScoreBoard. IPC::ScoreBoard 
can only store integer values but it does that without locking. Instead it 
uses atomic operations provided by the hardware. That module is quite new. So 
you might expect bugs.

Another module that I use quite extensively is MMapDB. It might be better 
suited to your task.

Torsten Förtsch

-- 
Need professional modperl support? Hire me! (http://foertsch.name)

Like fantasy? http://kabatinte.net