Problems with DBI and fork()

1 minute read

I recently had a problem with a Perl script in connection with DBI.

The script opens a DBI connection to fetch some data and then forks some child’s based on this data. After the child completes its job the DB will be updated and that’s it mainly. The child doesn’t access the DB.

So my problem was the the DB handle became invalid suddenly and I had no clue why. After some debugging I noticed that it invalidated after the first child exited and I did the child reaping after the SIGCHLD.

I searched a bit for a solution and found an interesting article about Fork-safe DBI handles via ChildHandles and InactiveDestroy.

The problem is how fork() and DBI’s default behaviour work together. If I fork a child all existing variables are available in the child as well. The the child then exits during the global DESTROY a message is sent to the DB server that the connection is terminated. This invalidates the connection, although the child never used it.

Luckily you can set the InactiveDestroy attribute on the handle directly after the child is forked. This will skip the database engine related effects during the DESTROY.

$dbh->{InactiveDestroy} = 1

However you’re free to call disconnect directly to destroy the handle manually.

Further information can be either found in the article mentioned above with a very interesting code snippet to do this on all inherited handles or in the DBI documentation