fix(logging): Fix deadlock in log batcher #5684
2 issues
Medium
Missing re-entry check in flush() method could still cause deadlock - `sentry_sdk/_batcher.py:117-122`
The flush() method sets self._active.flag = True but does not check if the flag is already True before proceeding, unlike the add() method. If code running during the locked section of _flush() (lines 146-151 where self._lock is held) triggers a re-entrant call to flush() on the same thread, it would attempt to acquire the non-reentrant threading.Lock() again, causing a deadlock. The fix adds protection for add() but leaves flush() vulnerable to the same class of re-entrant deadlock.
Re-entry guard flag can be clobbered when flush() is called during add() execution - `sentry_sdk/_batcher.py:117-122`
The flush() method unconditionally sets _active.flag = True and then resets it to False in its finally block. If flush() is called while add() is already executing on the same thread (e.g., via a callback triggered during _ensure_thread() or buffer operations), the finally block in flush() will reset the flag to False while add() is still running. This breaks the re-entry guard for the remainder of add()'s execution, allowing a subsequent re-entrant call to proceed and potentially cause the deadlock this PR aims to prevent.
4 skills analyzed
| Skill | Findings | Duration | Cost |
|---|---|---|---|
| code-review | 1 | 59.5s | $0.20 |
| find-bugs | 1 | 1m 37s | $0.26 |
| skill-scanner | 0 | 43.1s | $0.18 |
| security-review | 0 | 31.1s | $0.13 |
Duration: 3m 51s · Tokens: 285.5k in / 8.4k out · Cost: $0.78 (+fix_gate: $0.00, +extraction: $0.01, +dedup: $0.00)