diff --git a/src/jrd/Attachment.h b/src/jrd/Attachment.h index bb8249e704..bc8565a0e4 100644 --- a/src/jrd/Attachment.h +++ b/src/jrd/Attachment.h @@ -277,6 +277,7 @@ public: dsql_dbb* att_dsql_instance; bool att_in_use; // attachment in use (can't be detached or dropped) int att_use_count; // number of API calls running except of asynchronous ones + ThreadId att_purge_tid; // ID of thread running purge_attachment() EDS::Connection* att_ext_connection; // external connection executed by this attachment ULONG att_ext_call_depth; // external connection call depth, 0 for user attachment @@ -392,7 +393,7 @@ const ULONG ATT_cancel_disable = 0x00200L; // Disable cancel operations const ULONG ATT_no_db_triggers = 0x00400L; // Don't execute database triggers const ULONG ATT_manual_lock = 0x00800L; // Was locked manually const ULONG ATT_async_manual_lock = 0x01000L; // Async mutex was locked manually -const ULONG ATT_purge_started = 0x02000L; // Purge already started - avoid 2 purges at once +//const ULONG ATT_purge_started = 0x02000L; // Purge already started - avoid 2 purges at once const ULONG ATT_system = 0x04000L; // Special system attachment const ULONG ATT_creator = 0x08000L; // This attachment created the DB const ULONG ATT_monitor_done = 0x10000L; // Monitoring data is refreshed diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index c4bb2f5b3f..215c8ccdde 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -5395,7 +5395,8 @@ static void check_database(thread_db* tdbb, bool async) status_exception::raise(Arg::Gds(isc_bug_check) << Arg::Str(string)); } - if ((attachment->att_flags & ATT_shutdown) || + if ((attachment->att_flags & ATT_shutdown) && + (attachment->att_purge_tid != Thread::getId()) || ((dbb->dbb_ast_flags & DBB_shutdown) && ((dbb->dbb_ast_flags & DBB_shutdown_full) || !attachment->locksmith()))) { @@ -6789,7 +6790,13 @@ static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsign Jrd::Attachment* attachment = sAtt->getHandle(); - while (attachment && (attachment->att_flags & ATT_purge_started)) + if (attachment && attachment->att_purge_tid == Thread::getId()) + { + fb_assert(false); // recursive call - impossible ? + return; + } + + while (attachment && attachment->att_purge_tid) { attachment->att_use_count--; @@ -6812,7 +6819,7 @@ static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsign return; fb_assert(attachment->att_flags & ATT_shutdown); - attachment->att_flags |= ATT_purge_started; + attachment->att_purge_tid = Thread::getId(); fb_assert(attachment->att_use_count > 0); attachment = sAtt->getHandle(); @@ -6876,10 +6883,14 @@ static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsign // and commit the transaction TRA_commit(tdbb, transaction, false); } - catch (const Exception&) + catch (const Exception& ex) { attachment->att_flags = save_flags; + string s; + s.printf("Database: %s\n\tError at disconnect:", attachment->att_filename.c_str()); + iscLogException(s.c_str(), ex); + if (dbb->dbb_flags & DBB_bugcheck) throw; @@ -6900,7 +6911,7 @@ static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsign { if (!nocheckPurge) { - attachment->att_flags &= ~ATT_purge_started; + attachment->att_purge_tid = 0; throw; } } @@ -6921,7 +6932,7 @@ static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsign { if (!nocheckPurge) { - attachment->att_flags &= ~ATT_purge_started; + attachment->att_purge_tid = 0; throw; } } @@ -7440,6 +7451,9 @@ ISC_STATUS thread_db::checkCancelState() if (attachment) { + if (attachment->att_purge_tid == Thread::getId()) + return FB_SUCCESS; + if (attachment->att_flags & ATT_shutdown) { if (database->dbb_ast_flags & DBB_shutdown)