Skip to content

Commit

Permalink
Don't call $sth->finish() when InactiveDestroy is set
Browse files Browse the repository at this point in the history
DBI already calls dbd_st_finish() before dbd_st_destroy() if the handle
is active. For inactive handles no finish() should be necessary. With
InactiveDestroy set, the handle is always considered inactive. Skipping
finish() could lead to "out of sync" situations and inconsistencies,
however, the attribute is explicitly meant to skip all DB-related
destroy actions, especially for the case when the connection will be
closed anyway.

The only thing which is not cleaned up by finish() is the last result.

This commit fixes the following example:

 $dbh->{'AutoInactiveDestroy'} = 1;
  my $sth = $dbh->prepare('SELECT id FROM bcwb_maint_types; SELECT SLEEP(1); SELECT text FROM bcwb_maint_types;');
  $sth->execute();
  my $i = 0;
  do {
    printf "Result %d\n", ++$i;
    while (my $id = $sth->fetchrow_array()) {
      print $id, "\n";
    }
    print "---\n";
    if ($i == 1) {
      if (my $pid = fork()) {
        waitpid($pid, 0);
      } else {
        exit(0);
      }
    }
  } while ($sth->more_results);
  • Loading branch information
rovo89 committed Nov 29, 2022
1 parent b1f4834 commit ff8dc1d
Showing 1 changed file with 2 additions and 7 deletions.
9 changes: 2 additions & 7 deletions dbdimp.c
Original file line number Diff line number Diff line change
Expand Up @@ -5441,13 +5441,8 @@ void mariadb_st_destroy(SV *sth, imp_sth_t *imp_sth) {
int num_params;
int num_fields;

if (!PL_dirty)
{
/* During global destruction, DBI objects are destroyed in random order
* and therefore imp_dbh may be already freed. So do not access it. */
mariadb_st_finish(sth, imp_sth);
mariadb_st_free_result_sets(sth, imp_sth, TRUE);
}
if (imp_sth->result)
mysql_free_result(imp_sth->result);

DBIc_ACTIVE_off(imp_sth);

Expand Down

0 comments on commit ff8dc1d

Please sign in to comment.