Problem: When UnifiedLock.__aexit__ encountered an exception during async_lock.release(), the error recovery logic would incorrectly attempt to release async_lock again because it only checked main_lock_released flag. This could cause: - Double-release attempts on already-failed locks - Masking of original exceptions - Undefined behavior in lock state Root Cause: The recovery logic used only main_lock_released to determine whether to attempt async_lock release, without tracking whether async_lock.release() had already been attempted and failed. Fix: - Added async_lock_released flag to track async_lock release attempts - Updated recovery logic condition to check both main_lock_released AND async_lock_released before attempting async_lock release - This ensures async_lock.release() is only called once, even if it fails Testing: - Added test_aexit_no_double_release_on_async_lock_failure: Verifies async_lock.release() is called only once when it fails - Added test_aexit_recovery_on_main_lock_failure: Verifies recovery logic still works when main lock fails - All 5 UnifiedLock safety tests pass Impact: - Eliminates double-release bugs in multiprocess lock scenarios - Preserves correct error propagation - Maintains recovery logic for legitimate failure cases Files Modified: - lightrag/kg/shared_storage.py: Added async_lock_released tracking - tests/test_unified_lock_safety.py: Added 2 new tests (5 total now pass) |
||
|---|---|---|
| .. | ||
| api | ||
| evaluation | ||
| kg | ||
| llm | ||
| tools | ||
| __init__.py | ||
| base.py | ||
| constants.py | ||
| exceptions.py | ||
| lightrag.py | ||
| namespace.py | ||
| operate.py | ||
| prompt.py | ||
| rerank.py | ||
| types.py | ||
| utils.py | ||
| utils_graph.py | ||