sqlite: totally indestructable

Today, I saw some SQLite failures occur when a process had consumed all its open filehandles with session databases. My first thought was that there was a circular reference preventing destruction. After an almost comical amount of struggle to get Devel::Cycle to work, and then an actually comical amount of struggle to get Devel::FindRef to not choke on DBI connections, the problem turned up. I’m pretty sure that I wrote the offending line. I feel fairly silly about it now, since it is a pretty clear one-line red flag. This is a close approximation:

$m->{_timer} = HTML::Mason::Timer->new(m => $m);

Ha!

Unfortunately, while this was clearly a good bug to fix, it didn’t solve the problem. The error log kept showing “closing dbh with active statement handles” even though everything relevant seemed to be calling $sth->finish. Finally, this helped:

sub DESTROY {
  my ($self) = @_;
  $_->finish for $self->{dbh}->ChildHandles; # This had to be added.
  $self->{dbh}->disconnect;
}

Yow! I wonder whether there are a huge pile of people being affected by this. Maybe not, since using SQLite for sessions required a bit of a hack.

Written on April 19, 2007
🐪 perl
🧑🏽‍💻 programming