FEAT: Connection.closed property by jahnvi480 · Pull Request #398 · microsoft/mssql-python

@jahnvi480

AI review requested due to automatic review settings

January 8, 2026 10:50

@jahnvi480 jahnvi480 changed the title FEAT: Exposing _closed() method for public FEAT: Connection.closed() property

Jan 8, 2026

bewithgaurav

@jahnvi480 jahnvi480 changed the title FEAT: Connection.closed() property FEAT: Connection.closed property

Jan 8, 2026

gargsaumya

dlevy-msft-sql added a commit to dlevy-msft-sql/mssql-python that referenced this pull request

Jan 16, 2026
…sor outlives connection

- Check connection.closed property before calling SQLFreeHandle in Cursor.close()
- Skip handle cleanup if parent connection is already closed (handles are invalid)
- Add early sys._is_finalizing() check in Cursor.__del__()
- Add 5 new tests covering the exact reproduction scenario from the issue

This fixes the case where:
1. Connection is closed (ODBC handles freed)
2. Cursor objects still exist in Python memory
3. GC runs during normal execution (not interpreter shutdown)
4. Cursor.__del__() tries to free invalid ODBC statement handle

PR microsoft#361 only checked sys.is_finalizing() which doesn't cover GC during normal execution.
This fix uses the Connection.closed property (from PR microsoft#398) to detect closed connections.

dlevy-msft-sql added a commit to dlevy-msft-sql/mssql-python that referenced this pull request

Jan 16, 2026
…sor outlives connection

- Check connection state before calling SQLFreeHandle in Cursor.close()
- Default to SAFE behavior: skip handle cleanup if connection is None/gone/closed
- Only free handle if we can CONFIRM connection is alive and open
- Add early sys._is_finalizing() check in Cursor.__del__()
- Add 5 new tests covering the exact reproduction scenario from the issue

This fixes the case where:
1. Connection is closed (ODBC handles freed)
2. Cursor objects still exist in Python memory
3. GC runs during normal execution (not interpreter shutdown)
4. Cursor.__del__() tries to free invalid ODBC statement handle

Key insight: The previous fix defaulted to 'not closed' when connection was None,
which caused crashes when the connection was garbage collected. Now we default to
'closed' (safe) and only free if we can confirm connection is alive and open.

PR microsoft#361 only checked sys.is_finalizing() which doesn't cover GC during normal execution.
This fix uses the Connection.closed property (from PR microsoft#398) to detect closed connections.