problem porting to threaded mode
am 01.01.2009 06:27:12 von Craig MacKennaTrying to shift our largely mod_perl2 web site to an Apache2 threaded
MPM and perl ithreads.
The following works under the non-threaded prefork MPM:
use DB_File;
my @dbs; # array of hash references
my @dbModTime; # mod times of db files
my @dbfns; # array of database pathnames
# executed before fork into child processes
sub post_config {
my $db;
my $s = $_[3];
# tie the DBs and get their mod times
for ($db = 0; $db < @dbfn; $db++) {
$dbs[$db] = {};
tie %{$dbs[$db]}, "DB_File", $dbfn[$db], O_RDONLY
or die ((caller 0)[3]. " can't tie " . $dbfn[$db] . ": $!");
$dbModTime[$db] = (CORE::stat($dbfn[$db]))[9]
or die ((caller 0)[3]. " can't stat " . $dbfn[$db] . ": $!");
} }
The routines that use the databases re-stat the DB files and untie and
re-tie a DB
that has changed. Each child process must do this for itself.
In the threaded environment, any thread within a process may discover
that such
an untie and re-tie is necessary, but such an operation should be
effective
for the other threads in the process as well. This means that @dbs and
@dbModTime should be shared among the threads:
use threads;
use threads::shared;
my @dbs :shared; # array of hash references
my @dbModTime :shared; # mod times of db files
Making only the changes above makes perl complain "Invalid value for
shared scalar"
about the '$dbs[$db] = {};' line. This error message can be fixed as
follows:
for ($db = 0; $db < @dbfn; $db++) {
$dbs[$db] = shared_clone({});
tie %{$dbs[$db]}, "DB_File", $dbfn[$db], O_RDONLY
or die ((caller 0)[3]. " can't tie " . $dbfn[$db] . ": $!");
$dbModTime[$db] = (CORE::stat($dbfn[$db]))[9]
or die ((caller 0)[3]. " can't stat " . $dbfn[$db] . ": $!");
$s->log->notice ($dbfn[$db]." has " .scalar(keys(%{$dbs[$db]}))."
entries");
}
Unfortunately, when this is done the server starts, but the DBs look
empty and
the log notices for each DB show "0 entries".
Removing the ':shared' tag for @dbs and the 'shared_clone()' wrapper
for '{}'
causes the log notices to show the proper number of entries for each DB,
but blows up the Apache configuration process (before the 'resuming
normal
operations' message) with
httpd in free(): error: chunk is already free
in error_log and the following on the terminal:
Abort trap (core dumped)
Error invoking apachectl start command
I guess not having databases is better. I've tried using @dbs as an
array of
references to named, shared hashes: also no database content. The
'worker'
and 'event' MPMs work identically w/r/t this problem.
Suggestions of things to try will be very welcome.
Happy New Year, cmac