ViceRaid has asked for the wisdom of the Perl Monks concerning the following question:

Good morning

I've recently been upgrading and rewriting a mod_perl Translation Handler. It's doing nothing too sophisticated, mainly just using a MySQL database to look up details based on an SSL certificate presented by the client.

So, one of the first things I do is to change the old function handler to being an object handler, and to abstract the storage of the client details, and write some nice tests. I ended up with something like this:

# in a startup.pl use Apache::DBI; my %args = ( 'dsn' => 'dbi:mysql:foo', 'user' => 'xx', 'pass' => 'xx'); # note this does a DBI->connect my $dbsource = MyProject::DBSource::MySQL->new(%dbargs); $My::TransHandler = MyProject::Handler->new('source' => dbsource); # in conf PerlTransHandler $My::TransHandler->handle

However, though it worked fine on my dev box, bad stuff started to happen when it went live on production. All was good for a while after restart, then more and more requests would start crawling. Looking at perrin's comment in this thread, it seems I've done a naughty thing in doing a DBI connect in startup.pl. The enlightenment I seek is why I shouldn't do this, and whether this seems a likely explanation for the problems I was seeing when the code went live.

I'll be cheeky, and ask a supplementary question: any tips for integration testing this sort of thing?

With thanks
ViceRaid

Replies are listed 'Best First'.
Re: Objects, Object Handlers and mod_perl
by aquarium (Curate) on Jun 05, 2003 at 11:03 UTC
    i don't know much about perl OO, but it seems to me like your test box was not caching the perl mod and the production box does...as per the thread by perrin. basically (in a cached mod_perl environment) global variables persist across sessions/programs (which are using the same instance of the perl binary. In such an environment the first thing you should do is see if you are running as such and re-initialize variables, being careful about DBI especially, as it can separately (from perl) cache db handles. the usual way of doing this is to set a variable in the top of the code just after testing if it's been set. E.g. if ($been_here) {reinitialize stuff} else {$been_here=1; initialize stuff} rest of code goes here. It will make more sense to you probably if you write a little re-entrant form processor cgi, i.e. the form is spat out by the cgi and the submit also goes to the cgi. hope some of this has made sense.
Re: Objects, Object Handlers and mod_perl
by edoc (Chaplain) on Jun 05, 2003 at 12:58 UTC

    I think the basic deal is that by connecting in startup.pl you are then passing the same connection to each Apache child when each spawns so then they are all trying to use the same connection which just screws things up. On the other hand if you connect inside the handler then each child makes it's own connection which is the way it's meant to be.. 8)

    cheers,

    J

      That's right. You can't share a socket across a fork like that. Take a look at Apache::DBI's connect_on_init() instead.