You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On the 1.x line (tested with firebird-driver 1.10.11 / firebird-base 1.8.0), letting the garbage collector finalize a Connection that was never closed segfaults the Python process. This is the same crash as #69. #72 fixed it on master on 2026-05-21, but that fix is not on release-1.x, and it is also not in any 2.x release yet (2.0.3 was published 2026-04-20).
On 1.x, iAttachment.detach() (the v5 override in interfaces.py) calls the native detach without the if self._refcnt: guard that iAttachment_v4.detach() has. During cyclic garbage collection the interface can be released first, and Connection.__del__ then detaches freed memory.
Minimal reproduction
Firebird 5.0.3 server, CPython 3.11.15, Linux x86_64, firebird-driver 1.10.11:
importgc, os, sysfromfirebird.driverimportconnect, driver_configdriver_config.fb_client_library.value=os.environ["FB_CLIENT_LIBRARY"]
DSN, PASSWORD=os.environ["FB_DSN"], os.environ["FB_PASSWORD"]
defabandon():
con=connect(DSN, user="SYSDBA", password=PASSWORD)
cur=con.cursor()
cur.execute("select count(*) from rdb$relations")
cur.fetchall()
# no con.close(): the connection is left to the garbage collectorforiinrange(100):
abandon()
gc.collect()
print("completed without crash")
Fatal Python error: Segmentation fault
File ".../firebird/driver/interfaces.py", line 1236 in detach
File ".../firebird/driver/core.py", line 1672 in __del__
File "repro.py", line 18 in <module>
With the #69 guard applied to release-1.x (if self._refcnt: around the native detach in the v5 iAttachment.detach()), the same script completes 100 iterations without a crash in 3 of 3 runs.
Impact
Any unclosed connection can crash the process when it is garbage collected. Examples include a connection pool that drops a connection it failed to close (a SQLAlchemy dialect whose terminate hook fails on invalidation), or application code that forgets close(). Applications that cannot move to 2.x yet (2.x requires firebird-base~=2.0 → protobuf~=5.29) are stuck on 1.10.11.
Summary
On the 1.x line (tested with firebird-driver 1.10.11 / firebird-base 1.8.0), letting the garbage collector finalize a
Connectionthat was never closed segfaults the Python process. This is the same crash as #69. #72 fixed it onmasteron 2026-05-21, but that fix is not onrelease-1.x, and it is also not in any 2.x release yet (2.0.3 was published 2026-04-20).On 1.x,
iAttachment.detach()(the v5 override ininterfaces.py) calls the nativedetachwithout theif self._refcnt:guard thatiAttachment_v4.detach()has. During cyclic garbage collection the interface can be released first, andConnection.__del__then detaches freed memory.Minimal reproduction
Firebird 5.0.3 server, CPython 3.11.15, Linux x86_64, firebird-driver 1.10.11:
Output (
python -X faulthandler repro.py), 3 of 3 runs, exit code 139:With the #69 guard applied to
release-1.x(if self._refcnt:around the native detach in the v5iAttachment.detach()), the same script completes 100 iterations without a crash in 3 of 3 runs.Impact
Any unclosed connection can crash the process when it is garbage collected. Examples include a connection pool that drops a connection it failed to close (a SQLAlchemy dialect whose terminate hook fails on invalidation), or application code that forgets
close(). Applications that cannot move to 2.x yet (2.x requiresfirebird-base~=2.0→protobuf~=5.29) are stuck on 1.10.11.Request
release-1.xand publish a 1.10.x release. A backport PR follows.