From 6e0e0c5a63b1146e25f086a7a485fa60cabf6334 Mon Sep 17 00:00:00 2001 From: Vlad Khorsun Date: Sun, 30 Nov 2025 18:38:34 +0200 Subject: [PATCH 1/2] This should fix bug #8817 : Fatal lock manager error: invalid lock id --- src/jrd/Relation.h | 1 + src/jrd/dfw.epp | 9 ++++++++- src/jrd/met.epp | 42 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/jrd/Relation.h b/src/jrd/Relation.h index 883d32ff2b7..4e7d7501224 100644 --- a/src/jrd/Relation.h +++ b/src/jrd/Relation.h @@ -399,6 +399,7 @@ const ULONG REL_jrd_view = 0x10000; // relation is VIEW const ULONG REL_gc_blocking = 0x20000; // request to downgrade\release gc lock const ULONG REL_gc_disabled = 0x40000; // gc is disabled temporarily const ULONG REL_gc_lockneed = 0x80000; // gc lock should be acquired +const ULONG REL_rescan = 0x100000; // rescan request was submitted while relation being scanning /// class jrd_rel diff --git a/src/jrd/dfw.epp b/src/jrd/dfw.epp index 5891bcb5010..363a6889a8e 100644 --- a/src/jrd/dfw.epp +++ b/src/jrd/dfw.epp @@ -6129,8 +6129,15 @@ static bool make_version(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_ DFW_post_work(transaction, dfw_scan_relation, NULL, relation->rel_id); // signal others about new format presence - LCK_lock(tdbb, relation->rel_rescan_lock, LCK_EX, LCK_WAIT); LCK_release(tdbb, relation->rel_rescan_lock); + { + // Use temp lock to avoid AST call + Lock tmpLock(tdbb, sizeof(SLONG), LCK_rel_rescan); + tmpLock.setKey(relation->rel_id); + + LCK_lock(tdbb, &tmpLock, LCK_EX, LCK_WAIT); + LCK_release(tdbb, &tmpLock); + } break; } diff --git a/src/jrd/met.epp b/src/jrd/met.epp index 1dbfbb4f322..5463bbb02c2 100644 --- a/src/jrd/met.epp +++ b/src/jrd/met.epp @@ -126,6 +126,7 @@ static void save_trigger_data(thread_db*, TrigVector**, jrd_rel*, JrdStatement*, const TEXT*, FB_UINT64, SSHORT, USHORT, const MetaName&, const string&, const bid*, Nullable ssDefiner); static void scan_partners(thread_db*, jrd_rel*); +static void scan_relation(thread_db*, jrd_rel*); static void store_dependencies(thread_db*, CompilerScratch*, const jrd_rel*, const MetaName&, int, jrd_tra*); static bool verify_TRG_ignore_perm(thread_db*, const MetaName&); @@ -3892,6 +3893,27 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation) * Scan a relation for view RecordSelExpr, computed by expressions, missing * expressions, and validation expressions. * + **************************************/ + + while (!(relation->rel_flags & (REL_scanned | REL_deleted))) + { + scan_relation(tdbb, relation); + } +} + + +static void scan_relation(thread_db* tdbb, jrd_rel* relation) +{ +/************************************** + * + * s c a n _ r e l a t i o n + * + ************************************** + * + * Functional description + * Scan a relation for view RecordSelExpr, computed by expressions, missing + * expressions, and validation expressions. + * **************************************/ SET_TDBB(tdbb); TrigVector* triggers[TRIGGER_MAX]; @@ -3915,6 +3937,10 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation) return; relation->rel_flags |= REL_being_scanned; + + LCK_lock(tdbb, relation->rel_rescan_lock, LCK_SR, LCK_WAIT); + relation->rel_flags &= ~REL_rescan; + dependencies = (relation->rel_flags & REL_get_dependencies) ? true : false; sys_triggers = (relation->rel_flags & REL_sys_triggers) ? true : false; relation->rel_flags &= ~(REL_get_dependencies | REL_sys_triggers); @@ -4217,9 +4243,14 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation) relation->replaceTriggers(tdbb, triggers); } - LCK_lock(tdbb, relation->rel_rescan_lock, LCK_SR, LCK_WAIT); relation->rel_flags &= ~REL_being_scanned; + if (relation->rel_flags & REL_rescan) + { + LCK_release(tdbb, relation->rel_rescan_lock); + relation->rel_flags &= ~(REL_scanned | REL_rescan); + } + relation->rel_current_format = NULL; } // try @@ -4526,8 +4557,13 @@ static int rescan_ast_relation(void* ast_object) AsyncContextHolder tdbb(dbb, FB_FUNCTION, relation->rel_rescan_lock); - LCK_release(tdbb, relation->rel_rescan_lock); - relation->rel_flags &= ~REL_scanned; + if (relation->rel_flags & REL_being_scanned) + relation->rel_flags |= REL_rescan; + else + { + LCK_release(tdbb, relation->rel_rescan_lock); + relation->rel_flags &= ~REL_scanned; + } } catch (const Firebird::Exception&) {} // no-op From 30cfa06c3571cb95e14c7009603184dd5480ba5b Mon Sep 17 00:00:00 2001 From: Vlad Khorsun Date: Tue, 2 Dec 2025 16:41:07 +0200 Subject: [PATCH 2/2] Assertion, as @dyemanov suggests. --- src/jrd/met.epp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/jrd/met.epp b/src/jrd/met.epp index 5463bbb02c2..e413dc43573 100644 --- a/src/jrd/met.epp +++ b/src/jrd/met.epp @@ -3933,8 +3933,7 @@ static void scan_relation(thread_db* tdbb, jrd_rel* relation) try { - if (relation->rel_flags & (REL_scanned | REL_deleted)) - return; + fb_assert(!(relation->rel_flags & (REL_scanned | REL_deleted))); relation->rel_flags |= REL_being_scanned;