Apache-forks
view release on metacpan or search on metacpan
0.03 January 13 2008
Correct potential issue with forks::shared namespace if user loaded threads::shared in
a PerlRequire (startup.pl) script.
Added support for forks::BerkeleyDB (Apache::forks::BerkeleyDB).
General improvements to framework for better module load order control.
Various POD updates.
Added more examples to distribution directory 'eg'.
0.02 January 7 2008
Improved mod_perl 1.x support.
Fixed a few bugs in child handler.
Silenced some warnings.
Added a few new sections to the POD.
Updated test suite to correctly support forks 0.24+ standard threads exit() behavior.
0.01 1 May 2007
First public version.
--- #YAML:1.0
name: Apache-forks
version: 0.03
abstract: Transparent Apache ithreads interface using forks
license: ~
generated_by: ExtUtils::MakeMaker version 6.36
distribution_type: module
requires:
Devel::Required: 0.07
forks: 0.26
mod_perl: 0
Test::More: 0
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.2.html
Makefile.PL view on Meta::CPAN
use strict;
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
eval "use Devel::Required";
WriteMakefile (
NAME => 'Apache::forks',
AUTHOR => 'Eric Rybski (rybskej@yahoo.com)',
ABSTRACT => 'Transparent Apache ithreads interface using forks',
VERSION_FROM => 'lib/Apache/forks.pm',
PREREQ_PM => {
'Devel::Required' => 0.07,
'forks' => 0.26,
'mod_perl' => 0,
'Test::More' => 0,
},
(MM->can('signature_target') ? (SIGN => 1) : ()),
);
Apache::forks - Transparent Apache ithreads integration using forks
Version:
0.03
DESCRIPTION
See "perldoc Apache::forks" (or "perldoc forks.pm") for details.
Required Modules:
Devel::Required (0.07)
eg/mycache.pm view on Meta::CPAN
package mycache;
use threads;
use threads::shared;
our %cache : shared = (dummy=>'ok');
1;
eg/printenv.cgi view on Meta::CPAN
#!/usr/bin/perl
##
## printenv -- demo CGI program which just prints its environment
##
use threads;
use threads::shared;
use Data::Dumper;
use Benchmark qw(:all);
print "Content-type: text/plain\n\n";
### print environment details ###
foreach $var (sort(keys(%ENV))) {
$val = $ENV{$var};
$val =~ s|\n|\\n|g;
$val =~ s|"|\\"|g;
print "${var}=\"${val}\"\n";
}
print Dumper(\%INC);
print "\nmy tid=";
print threads->tid,"\n";
### create some threads ###
my @threads;
push @threads, threads->new(sub {
sleep 1;
}) for 1..5;
$_->join foreach @threads;
print "ok, we joined all locally-created threads (".scalar(@threads).")\n";
### test global hash cache ###
$mycache::cache{counter}++;
print Dumper(\%mycache::cache);
### test performance of global vars ###
timethis (-5, sub { $mycache::cache{somevar}++ } );
lib/Apache/forks.pm view on Meta::CPAN
}
1;
__END__
=pod
=head1 NAME
Apache::forks - Transparent Apache ithreads integration using forks
=head1 VERSION
This documentation describes version 0.03.
=head1 SYNOPSIS
# Configuration in httpd.conf
PerlModule Apache::forks # this should come before all other modules!
Do NOT change anything in your scripts. The usage of this module is transparent.
=head1 DESCRIPTION
Transparent Apache ithreads integration using forks. This module enables the
ithreads API to be used among multiple processes in a pre-forking Apache http
environment.
=head1 REQUIRED MODULES
Devel::Required (0.07)
forks (0.26)
mod_perl (any)
Test::More (any)
=head1 USAGE
lib/Apache/forks.pm view on Meta::CPAN
A Common usage is to load the module in a startup file via the PerlRequire
directive. See C<eg/startup.pl> in this distribution. In this case, be sure
that the module is first to load in the startup script, and that the
PerlRequre directive to load the startup script is the first mod_perl directive
in your httpd.conf file.
Please see the C<eg/> directory in this distribution for other examples.
=head1 NOTES
=head2 mod_perl processes start as detached threads
CGI scripts may behave differently when using forks with mod_perl, depending
on how you have implemented threads in your scripts. This is frequently due to
the difference in the thread group behavior: every mod_perl handler (process)
is already a thread when your CGI starts executing, and all CGIs executing
simultaneously on your Apache server are all part of the same application
thread group. Your script is no longer executed as the main thread
(Thread ID 0); it is just a detached child thread in the executing thread group.
This differs from pure CGI-style execution, where every CGI has its own unique
thread group (isolated from all other Apache process handlers) and each CGI
always begins execution as the main thread.
=head2 threads->list and $thr->join differences in mod_perl
Methods that operate other threads should be treated with care. For example, if you
were successfully doing the following in CGI:
threads->new({'context' => 'scalar'}, sub {...}) for 1..5;
push @results, $_->join foreach threads->list(threads::running); #<-- don't do this
or
threads->new({'context' => 'scalar'}, sub {...}) for 1..5;
$_->join foreach threads->list(threads::joinable); #<-- don't do this
the join operation may inadvertantly join threads started by from other Apache
handler processes executing threaded code at the same time!
Do the following in mod_perl instead:
push @my_threads, threads->new({'context' => 'scalar'}, sub {...}) for 1..5;
push @results, $_->join foreach @my_threads;
or
push @my_threads, threads->new({'context' => 'scalar'}, sub {...}) for 1..5;
$_->join foreach map($_->is_joinable ? $_ : (), @my_threads);
The good news about making such logic changes is that they will work both in CGI
and mod_perl modes. If you code all your threaded CGIs in this style, your code
should work fine without changes when switching to mod_perl.
=head1 TODO
Determine why mod_perl appears to skip END blocks of child threads (threads
started in an apache-forked handler process) that complete and exit safely.
This isn't necessarily harmful, but should be resolved to insure highest level
of application and memory stability.
=head1 CAVIATS
This module will only work with Apache httpd 1.3.0 or newer. This is due to the
lack of mod_perl support for PerlChildInitHandler directive. See L<mod_perl/"mod_perl">
for more information regarding this.
For Apache 2.x, this module currently only supports the MPM (Multi-Processing Module)
L<http://httpd.apache.org/docs/2.0/mod/prefork.html#prefork>.
This is due to the architecture of L<forks>, which only supports one perl thread per
process.
=head1 BUGS
=head1 CREDITS
=over
=item Apache::DBI
lib/Apache/forks/BerkeleyDB.pm view on Meta::CPAN
}
1;
__END__
=pod
=head1 NAME
Apache::forks::BerkeleyDB - Transparent Apache ithreads integration using forks::BerkeleyDB
=head1 VERSION
This documentation describes version 0.03.
=head1 SYNOPSIS
# Configuration in httpd.conf
PerlModule Apache::forks::BerkeleyDB # this should come before all other modules!
Do NOT change anything in your scripts. The usage of this module is transparent.
=head1 DESCRIPTION
Transparent Apache ithreads integration using forks::BerkeleyDB. This module enables the
ithreads API to be used among multiple processes in a pre-forking Apache http
environment.
=head1 USAGE
The module should be loaded upon startup of the Apache daemon. You must be
using at least Apache httpd 1.3.0 or 2.0 for this module to work correctly.
Add the following line to your httpd.conf:
PerlModule Apache::forks::BerkeleyDB
lib/Apache/forks/Common.pm view on Meta::CPAN
else {
require mod_perl;
if (defined $mod_perl::VERSION && $mod_perl::VERSION > 1 &&
$mod_perl::VERSION < 1.99) {
require Apache;
#not using Apache::fork support yet (may be non-portable and/or deprecated)
# require Apache::fork;
# Apache::fork::forkoption(1);
# no warnings 'redefine';
# *threads::_fork = \&Apache::fork::fork;
} else {
die "Apache.pm is unavailable or unsupported version ($mod_perl::VERSION)";
}
}
}
### functions ###
sub DEBUG { $DEBUG = shift() ? 1 : 0; }
sub debug {
print STDERR "$_[1]\n" if $DEBUG >= $_[0] || threads->debug >= $_[0];
}
sub _load_forks {
my $self = shift;
$BASE = $self->BASE;
$forks::DEFER_INIT_BEGIN_REQUIRE = 1;
eval 'require '.$self->_forks();
die "forks version 0.26 or later required--this is only version $forks::VERSION"
unless defined($forks::VERSION) && $forks::VERSION >= 0.26;
eval 'import '.$self->_forks(); #set environment and preload server process
eval 'require '.$self->_forks_shared();
eval 'import '.$self->_forks_shared(); #set environment
{
no warnings 'redefine';
my $old_server_pre_startup = \&threads::_server_pre_startup;
*threads::_server_pre_startup = sub {
unless ($self->DEBUG) {
### close IO pipes to silence possible warnings to terminal ###
close(STDERR);
close(STDOUT);
close(STDIN);
}
$old_server_pre_startup->()
if ref($old_server_pre_startup) eq 'CODE';
};
}
}
sub childinit {
threads->isthread;
my $timestamp = localtime(time);
debug(1, "[$timestamp] [notice] $$:".threads->tid
." Apache::$BASE PerlChildInitHandler executed");
1;
}
### methods ###
sub _forks { return shift->BASE; }
sub _forks_shared { return shift->BASE.'::shared'; }
sub import {
my $self = shift;
$self->_forks->import(@_);
$self->_forks_shared->import(); #kludge: insures correct %INC for forks::shared
my $timestamp = localtime(time);
if (MP2) {
if (!@Import) {
Carp::carp("Apache MPM '".Apache2::MPM->show()
."' is not supported: "
."This package can't be used under threaded MPMs: "
."Only 'Prefork' MPM is supported at this time\n")
and return if Apache2::MPM->is_threaded;
my $s = Apache2::ServerUtil->server;
$s->push_handlers(PerlChildInitHandler => \&childinit);
debug(1, "[$timestamp] [notice] $$:".threads->tid
." Apache::".$self->_forks." PerlChildInitHandler enabled");
}
} else {
Carp::carp("Apache.pm was not loaded\n")
and return unless $INC{'Apache.pm'};
if (!@Import and Apache->can('push_handlers')) {
Apache->push_handlers(PerlChildInitHandler => \&childinit);
debug(1, "[$timestamp] [notice] $$:".threads->tid
." Apache::".$self->_forks." PerlChildInitHandler enabled");
}
}
push @Import, [@_];
}
package
Apache::forks::common::shared; # hide from PAUSE
t/01_load.t view on Meta::CPAN
}
}
BEGIN {delete $ENV{THREADS_DEBUG}} # no debugging during testing!
BEGIN {
$ENV{MOD_PERL} = 'CGI-Perl';
$ENV{GATEWAY_INTERFACE} = 'CGI-Perl';
};
#use Apache::forks qw(stringify); # must be done _before_ Test::More which loads real threads.pm
use forks qw(stringify);
use forks::shared;
use Test::More tests => 2;
SKIP: {
my $thread1 = threads->new( sub { 1 });
$thread1->join();
is( "$thread1", $thread1->tid, "Check that stringify works" );
my $ptid = threads->tid;
unless (my $pid = fork) {
threads->isthread if defined($pid);
isnt( threads->tid, $ptid, "Check that ->isthread works");
threads->can('exit') ? threads->exit : exit;
}
sleep 3; # make sure fork above has started
}
1;
t/02_load_bdb.t view on Meta::CPAN
}
}
BEGIN {delete $ENV{THREADS_DEBUG}} # no debugging during testing!
BEGIN {
$ENV{MOD_PERL} = 'CGI-Perl';
$ENV{GATEWAY_INTERFACE} = 'CGI-Perl';
};
#use Apache::forks::BerkeleyDB qw(stringify); # must be done _before_ Test::More which loads real threads.pm
my ($forks_bdb_installed, $reason);
BEGIN {
$forks_bdb_installed = 0;
eval {
require forks::BerkeleyDB;
import forks::BerkeleyDB qw(stringify);
require forks::BerkeleyDB::shared;
import forks::BerkeleyDB::shared;
};
$reason = $@ if $@;
$forks_bdb_installed = 1 unless $@;
}
use Test::More ($forks_bdb_installed ? (tests => 2) : (skip_all => $reason));
SKIP: {
my $thread1 = threads->new( sub { 1 });
$thread1->join();
is( "$thread1", $thread1->tid, "Check that stringify works" );
my $ptid = threads->tid;
unless (my $pid = fork) {
threads->isthread if defined($pid);
isnt( threads->tid, $ptid, "Check that ->isthread works");
threads->can('exit') ? threads->exit : exit;
}
sleep 3; # make sure fork above has started
}
1;
( run in 0.327 second using v1.01-cache-2.11-cpan-3cd7ad12f66 )