Skip to content

Commit b2ecee4

Browse files
febus982claude
andcommitted
Fix atexit handler for async drivers during shutdown
Use close=False when disposing engines in the atexit handler to avoid MissingGreenlet errors with async drivers (e.g., aiosqlite) that require an event loop context to close connections. The OS will clean up connections when the process exits. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 33c31ac commit b2ecee4

1 file changed

Lines changed: 14 additions & 4 deletions

File tree

sqlalchemy_bind_manager/_bind_manager.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,18 +91,24 @@ def __init__(
9191
self.__init_bind(DEFAULT_BIND_NAME, config)
9292
SQLAlchemyBindManager._instances.add(self)
9393

94-
def _dispose_sync(self) -> None:
94+
def _dispose_sync(self, close: bool = True) -> None:
9595
"""Dispose all engines synchronously.
9696
9797
This method is safe to call from any context, including __del__
9898
and atexit handlers. For async engines, it uses the underlying
9999
sync_engine to perform synchronous disposal.
100+
101+
Args:
102+
close: If True (default), also close all currently checked-in
103+
connections. Set to False during interpreter shutdown to
104+
avoid issues with async drivers (e.g., aiosqlite) that
105+
require an event loop to close connections.
100106
"""
101107
for bind in self.__binds.values():
102108
if isinstance(bind, SQLAlchemyAsyncBind):
103-
bind.engine.sync_engine.dispose()
109+
bind.engine.sync_engine.dispose(close=close)
104110
else:
105-
bind.engine.dispose()
111+
bind.engine.dispose(close=close)
106112

107113
def __del__(self) -> None:
108114
self._dispose_sync()
@@ -230,6 +236,10 @@ def _cleanup_all_managers() -> None:
230236
This ensures all SQLAlchemyBindManager instances have their engines
231237
disposed before the interpreter exits, even if __del__ hasn't been
232238
called yet due to reference cycles or other GC timing issues.
239+
240+
Uses close=False to avoid issues with async drivers (e.g., aiosqlite)
241+
that require an event loop context to close connections. The OS will
242+
clean up connections when the process exits.
233243
"""
234244
for manager in list(SQLAlchemyBindManager._instances):
235-
manager._dispose_sync()
245+
manager._dispose_sync(close=False)

0 commit comments

Comments
 (0)