Bug Description
SQLiteManager.close() is the only public method on the class that does not acquire self._lock before touching self.connection. Under concurrency, a close() call from one thread while another is mid-transaction (e.g., in add_history) can:
- Read self.connection as valid, close it, set it to None
- The other thread then calls self.connection.execute("COMMIT") on None, crashing with AttributeError
- The except handler in the other thread also tries ROLLBACK on None, masking the original error
The same risk applies via del which calls close() without the lock.
Fix
Add with self._lock: to close().
Bug Description
SQLiteManager.close() is the only public method on the class that does not acquire self._lock before touching self.connection. Under concurrency, a close() call from one thread while another is mid-transaction (e.g., in add_history) can:
The same risk applies via del which calls close() without the lock.
Fix
Add with self._lock: to close().