From 5d98d93bcedf3317f4ff739841162b521403662a Mon Sep 17 00:00:00 2001 From: Dianne Skoll Date: Wed, 12 Aug 2020 08:44:07 -0400 Subject: [PATCH] Work around a segfault during handle destruction. This patch fixes https://github.com/perl5-dbi/DBD-Oracle/issues/111 During global destruction, the function dbd_dr_destroy is sometimes called before all handles are destroyed. It frees resources uses in the handle DESTROY function, causing a segfault when the handle DESTROY function tries to disconnect the handle. This patch simply sets a flag in dbd_dr_destroy which makes per-handle DESTROY functions skip trying to disconnect the handle. --- dbdimp.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dbdimp.c b/dbdimp.c index 210a69d2..ca5a4ca6 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -51,6 +51,7 @@ ub2 utf8_csid = 871; ub2 al32utf8_csid = 873; ub2 al16utf16_csid = 2000; +static int dbd_dr_destroy_called = 0; typedef struct sql_fbh_st sql_fbh_t; struct sql_fbh_st { @@ -199,6 +200,7 @@ dbd_init(dbistate_t *dbistate) dTHX; DBIS = dbistate; dbd_init_oci(dbistate); + dbd_dr_destroy_called = 0; } @@ -208,6 +210,8 @@ dbd_dr_destroy(SV *drh, imp_drh_t *imp_drh) dTHX; sword status; + dbd_dr_destroy_called = 1; + /* We rely on the DBI dispatcher to destroy all child handles before we get here (DBI >= 1.623). */ if (imp_drh->leak_state) { @@ -1167,6 +1171,11 @@ dbd_db_disconnect(SV *dbh, imp_dbh_t *imp_dbh) /* since most errors imply already disconnected. */ DBIc_ACTIVE_off(imp_dbh); + /* If dbd_dr_destroy has been called, it's completely */ + /* unsafe to do anything with the handle, so just return */ + if (dbd_dr_destroy_called) { + return 1; + } /* Oracle will commit on an orderly disconnect. */ /* See DBI Driver.xst file for the DBI approach. */