Skip to content

Conversation

goedderz
Copy link
Member

@goedderz goedderz commented Aug 21, 2025

Scope & Purpose

This fixes a possible race with the async-prefetch optimizer rule. In certain situations, a prefetch task could still live and hold a valid result (in particular an AqlItemBlock) when the query was being destroyed. In that case, returning the AqlItemBlock during destruction would be a use-after-free of the AqlItemBlockManager, which is destroyed with the query.

A possible order of events was as follows:

  • A block with async-prefetch is called, fetches its first input block, and starts an async prefetch task.
  • Its executor is executed, and throws an exception.
  • Meanwhile, the async prefetch task starts executing (i.e. status is InProgress).
  • The query stops all async tasks. It waits for the running one to finish.
  • The async prefetch task finishes execution (i.e. saves the result, and sets its status to Finished), but does not yet return and destroy the shared_ptr to PrefetchTask.
  • The query is destroyed, and with it the AqlItemBlockManager.

Now in this situation, the result in the prefetch task - an AqlItemBlockInputRange - holds a SharedAqlItemBlockPtr to an AqlItemBlock that has outlived its AqlItemBlockManager, triggering the assertion (and use-after-free in a production setting).

  • 💩 Bugfix

Checklist

  • Tests
    • Regression tests
  • 📖 CHANGELOG entry made
  • Backports (versions before 3.12 aren't affected, as they did not contain the affected optimizer rules)

Related Information

This is a follow-up to #21709 and #21861.

@goedderz goedderz self-assigned this Aug 21, 2025
@cla-bot cla-bot bot added the cla-signed label Aug 21, 2025
@goedderz goedderz marked this pull request as ready for review August 21, 2025 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant