I recently upgraded from a rather old Perl/DBD::Sybase/FreeTDS installation to the current release versions, and I started hitting a problem where, on a DB error, my perl processes would expand to take up all the RAM on the system. I eventually traced the problem to the exception I throw in my DBI HandleError subroutine.

The memory problem might relate to the stack trace the exception tries to record (although disabling it doesn't seem to help), but the underlying cause seems to be with DBD::Sybase or perhaps DBI itself. When I feed selectrow_arrayref (or other similar functions) SQL that is a) wrong (e.g. references nonexistent columns) and b) contains placeholders, and then call "die" on the error string in the HandleError routine, I sometimes get a result like this:

	(in cleanup) DBD::Sybase::st DESTROY failed: Server message number=8179 severity=16 state=2 line=1 server=XXX text=Could not find prepared statement with handle 0.  at lib/LSPDB.pm line 27.
DBD::Sybase::db selectrow_hashref failed: Server message number=8179 severity=16 state=2 line=1 server=XXX text=Could not find prepared statement with handle 0.  at lib/LSPDB.pm line 27.

I'm no expert on Perl internals, but from poking around it seems that that "(in cleanup)" (which isn't from my code) implies that my error handler is being called while (or after?) a statement handler internal to the selectrow_hashref call is DESTROYed. And I can see why throwing an exception in that kind of context could lead to trouble (although just dying seems to work OK, except for the extra message.)

I would rather not completely restructure my code, especially because I'm not sure it would help. I'm stuck with this SQL Server DB, and I've tried using ODBC with Microsoft's driver, and that's its own nightmare. So what I'd like to know is:

  1. Am I just doing something dumb?
  2. If I'm not just doing something dumb, is there some way of detecting that code is running as part of a DESTROY routine? (If I assume the database handle error will come through, I could presumably just skip the statement handle error, but sometimes I do prepare/execute so I don't want to skip it in every case.)

Here's a code snippet for reference, where calling make_trouble() will reproduce the error (although similar code doesn't always, so there's probably a race condition). And obviously without an actual DBD::Sybase compatible server it won't run.

package LSPDB; use DBI; sub make_trouble { my $dbh = _connect(); return $dbh->selectrow_hashref("SELECT bar FROM course where foo = ? +", {}, 1); } sub _connect { my $db_options = { HandleError => \&_db_handle_error, AutoCommit => 1, }; my $_dbh = DBI->connect( 'DBI:Sybase:server=foo;database=bar', 'theus +er', 'thepass', $db_options, ); return $_dbh; } sub _db_handle_error { my ($errstr, $dbh, $ret) = @_; die $errstr; } 1;

In reply to DBI DESTROY problem by skef

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.