You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by cr...@animalhead.com on 2009/01/01 06:27:12 UTC

problem porting to threaded mode

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