Trying 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

Reply via email to