DBI, forking, and losing mysql connections

Ovid on 2007-03-02T16:02:57

Several hours later, I can finally lean back and relax after a one-line change in a program fixed a bug that another programmer and I spent hours failing to solve. Naturally, I found the solution two minutes after he left for the weekend, so I can't even crow about it until Monday.

We have a program which forks off several children to query whois servers. Unfortunately, the parent database handle was usually, but not always, going away. When it did go away it appeared to do so at random places in the code. The programmer who wrote the code was careful to ensure that each child was creating their own database handle, but I noticed in the code that 'connect_cached' was being used by default. Worried that everyone was sharing a database handle, I forced it to not used a cached copy if the PID was different, but my database handle still kept going away.

Eventually, we disabled the forking code and the problem went away, so we knew it was forking related. After many attempts to fix the problem, we were ready to table it until Monday with the consideration of possibly disabling the feature on our Web site.

That's when I stumbled across this post on Perlmonks. The symptoms were identical to ours. runrig, my hero for the day, mentioned the DBI InactiveDestroy attribute. Setting this to a true value in the parent (but not the child) eliminated the implicit disconnect that was apparently happening in the DBI DESTROY. I still have no idea why child finalization was killing the parent process (and doing so randomly, I might add), but the cargo-culted solution has saved the day.


Heh...

Matts on 2007-03-02T16:26:34

I think SpamAssassin is going through something like this right now too :-)

Same problem?

malte on 2007-03-02T18:56:59

Wow, looks like we're having the same problem right now. We had to temporarily disable most of the functionality of a website (due to changed laws in germany) which lowered the usage of the website's application to almost zero. Could this stuff also happen on a low traffic mod_perl website?

Took me ages to figure out too..

dgl on 2007-03-02T19:55:22

I've seen the same thing, presumably the MySQL protocol has some sort of quit command which the child process is sending (rather than simply closing the handle which would be OK).

I worked around it by bypassing destroy handlers via POSIX::_exit, but looks like InactiveDestroy is a better approach.