fix: ensure exception safety in incremental Add (#1870) by thlurte · Pull Request #1891 · zilliztech/knowhere · GitHub
Skip to content

fix: ensure exception safety in incremental Add (#1870) - #1891

Open
thlurte wants to merge 2 commits into
zilliztech:mainfrom
thlurte:fix/issue-1870-exception-safety
Open

thlurte wants to merge 2 commits into
zilliztech:mainfrom
thlurte:fix/issue-1870-exception-safety

Conversation

@thlurte

@thlurte thlurte commented Oct 15, 2026

Copy link
Copy Markdown

issue: #1870

Summary

  • Sparse Inverted Index (SparseInvertedIndexNodeCC::Add):
    • Advance next_task_id_ only after add_tasks_.push(task_id) succeeds under the mutex. If the push throws (e.g. std::bad_alloc), no task sequence gap is created that could block subsequent adds.
    • Install an RAII AddTaskGuard immediately after enqueue so that add_tasks_.pop(), current_task_id_++, and cv_.notify_all() are guaranteed to execute during stack unwinding on any exception.
    • Pass config by const auto& reference instead of copying to eliminate unnecessary allocations.
  • SCANN_DVR / OpenMP (ProductQuantizer):
    • Catch exceptions across OpenMP parallel regions in compute_codes and decode using faiss::omp_capture_exception and safely rethrow them via faiss::omp_rethrow_if_exception after thread join, preventing std::terminate.
  • Regression Unit Tests:
    • Added TEST_CASE("Test Sparse Inverted Index CC Exception Safety on Enqueue and Add", "[sparse][cc][exception_safety]") to tests/ut/test_sparse.cc.
    • Injects allocation failures during both enqueue and post-enqueue insert, verifying that subsequent Add and asynchronous Search calls complete within a bounded timeout without deadlocking.

Test Plan

  • Ran unit tests: knowhere_tests '[sparse][cc][exception_safety]': 24 assertions passed across both SPARSE_INVERTED_INDEX_CC and SPARSE_WAND_CC.
  • Ran existing sparse CC suite: knowhere_tests 'Test SINDI Sparse Inverted Index CC*': 21 assertions passed with zero regressions.
  • Pre-commit validation passed: check-added-large-files, check-merge-conflict, end-of-file-fixer, trailing-whitespace, and clang-format.
  • Git diff whitespace and DCO sign-off verified.

@sre-ci-robot

Copy link
Copy Markdown
Collaborator

@sre-ci-robot

Copy link
Copy Markdown
Collaborator

Welcome @thlurte! It looks like this is your first PR to zilliztech/knowhere 🎉

- Advance next_task_id_ only after successful enqueue under mutex to prevent task sequence gaps
- Use RAII AddTaskGuard in SparseInvertedIndexNodeCC::Add to guarantee task release and notification on exception
- Pass config by const reference to eliminate unnecessary heap allocation
- Capture and rethrow exceptions across OpenMP parallel regions in ProductQuantizer to prevent std::terminate
- Add Catch2 regression test forcing allocation failure during enqueue and insert, asserting bounded completion

Fixes: zilliztech#1870
Signed-off-by: Ahmed <thlurte@gmail.com>
@thlurte
thlurte force-pushed the fix/issue-1870-exception-safety branch from 1f5de6e to f687fd1 Compare October 21, 2026 07:53
@mergify mergify Bot added ci-passed and removed ci-passed labels Oct 21, 2026
@alexanderguzhva

Copy link
Copy Markdown
Collaborator

/hold


void ProductQuantizer::decode(const uint8_t* code, float* x, size_t n) const {
int64_t n_signed = n;
std::exception_ptr ex;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should a change that does not affect the baseline faiss code (thirdparty/faiss), unless it is first pushed into the vanilla faiss (https://github.com/facebookresearch/faiss). So, please either introduce the change in the vanilla faiss by submitting the PR (and I'll ask Faiss team to review it quickly), or please add exception handlers outside of the baseline faiss code.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thlurte fyi

@thlurte

thlurte commented Oct 23, 2026 •

Copy link
Copy Markdown
Author

Hi @alexanderguzhva,

As suggested, I have submitted the upstream PR directly to Faiss:
👉 facebookresearch/faiss#5771

It wraps the OpenMP parallel loops in ProductQuantizer::compute_codes and ProductQuantizer::decode with Faiss's canonical exception capture and std::atomic<bool> interrupt pattern, passing the full Faiss test suite and clang-format checks. I have also synchronized the vendored ProductQuantizer.cpp in this PR with the exact same upstream patch.

Could you please help ask the Faiss team to review facebookresearch/faiss#5771? Thank you!

…tizer

Signed-off-by: Ahmed <thlurte@gmail.com>
@thlurte
thlurte force-pushed the fix/issue-1870-exception-safety branch from 34e69d7 to c703b29 Compare October 23, 2026 15:12
@mergify mergify Bot added dco-passed and removed needs-dco labels Oct 23, 2026
@alexanderguzhva

Copy link
Copy Markdown
Collaborator

@mergify mergify Bot added the ci-passed label Oct 24, 2026
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.

3 participants