Skip to content

Conversation

@TreeHunter9
Copy link
Contributor

Due to double locking of mainSync inside WorkerStableAttachment::fini() (AttSyncLockGuard + BackgroundContextHolder) EngineCheckout will become useless (it uses in LCK_fini() -> LockManager::shutdownOwner()). If EngineCheckout will not do its job, we can get a deadlock, for example inside LockManager::shutdownOwner():

	while (owner->own_ast_count)
	{
		{ // checkout scope
			LockTableCheckout checkout(this, FB_FUNCTION);
			callbacks.checkoutRun([] {
				Thread::sleep(10);
			});
		}

		owner = (own*) SRQ_ABS_PTR(owner_offset);
	}

If the AST will be called for our worker attachment we will be stuck in this loop, AST cannot continue its execution due to lock on mainSync and attachment cannot finish its own routine due to recursive lock.

This case can be reproduced with next steps.

1. Set `ParallelWorkers = 2` in firebird.conf;
2. Create index on some field;
3. Next steps need to be done instantly in one time:
3.1 Wait 1 minute until timeout will detach worker attachment;
3.2 Alter table for which the index was created to trigger the `rescan_ast_relation()` AST;

It's very hard to reproduce due to race condition nature of the bug, but it can still happen accidentally in production.

v5 is also affected by this bug.

- Do not lock `mainSync` second time, so that `EngineCheckout` can do its job;
@hvlad
Copy link
Member

hvlad commented Jan 27, 2026

Could you provide call stacks for two deadlocked threads ?

@hvlad hvlad self-assigned this Jan 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants