Skip to content

FIX: prevent AttributeError in __del__ on partially-initialized Cursor#646

Open
subrata-ms wants to merge 2 commits into
mainfrom
subrata-ms/Bug642
Open

FIX: prevent AttributeError in __del__ on partially-initialized Cursor#646
subrata-ms wants to merge 2 commits into
mainfrom
subrata-ms/Bug642

Conversation

@subrata-ms

@subrata-ms subrata-ms commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Work Item / Issue Reference

AB#45943

GitHub Issue: #642


Summary

This pull request improves the robustness of the Cursor class initialization and cleanup logic, ensuring that partially-initialized or half-constructed cursor objects are handled safely and do not cause unraisable exceptions during garbage collection. It also adds regression tests to prevent recurrence of related bugs.

Initialization and cleanup robustness:

  • The __init__ method in cursor.py now sets self.closed = False and self.hstmt = None as the very first statements, before any code that might raise an exception, ensuring that even partially-initialized Cursor instances have a consistent state for cleanup. [1] [2]
  • The close() method now safely checks for the existence of the closed attribute using getattr(self, "closed", True), preventing AttributeError if the attribute is missing (e.g., in half-initialized objects).
  • The __del__ method now uses the correct sys.is_finalizing() function (instead of the incorrect sys._is_finalizing()) and guards logging calls to prevent unraisable exceptions during interpreter shutdown.

Testing and regression prevention:

  • Adds test_cursor_del_half_initialized_cursor_no_errors and test_cursor_init_failure_leaves_consistent_state to ensure that half-initialized cursors do not raise unraisable exceptions during garbage collection and that failed initialization leaves the cursor and connection in a consistent, recoverable state.

@github-actions github-actions Bot added the pr-size: medium Moderate update size label Jun 25, 2026
@subrata-ms subrata-ms marked this pull request as ready for review June 25, 2026 10:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens mssql_python.cursor.Cursor lifecycle behavior to avoid unraisable exceptions during garbage collection when a Cursor is only partially initialized, and adds regression tests to prevent recurrence of the CI PytestUnraisableExceptionWarning seen in issue #642.

Changes:

  • Establishes Cursor cleanup invariants earlier in __init__ (closed=False, hstmt=None) so close()/__del__ can run safely even after initialization failures.
  • Makes Cursor.close() tolerant of instances missing the closed attribute (e.g., objects created via Cursor.__new__).
  • Fixes __del__ finalization check to use sys.is_finalizing() and guards debug logging during interpreter shutdown; adds lifecycle regression tests.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
mssql_python/cursor.py Makes cursor initialization/cleanup resilient to partial construction and interpreter shutdown edge cases.
tests/test_005_connection_cursor_lifecycle.py Adds regression tests for half-initialized cursor GC paths and failed cursor construction scenarios.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +481 to +489
with pytest.raises(RuntimeError, match="simulated HSTMT"):
conn.cursor()

# Force GC of any cursor instance __new__'d during the failed
# construction; no unraisable AttributeError must escape.
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
gc.collect()

Comment on lines +406 to +409
"""Regression: if ``Cursor.__init__`` raises before reaching
``self.closed = False`` (e.g. ``_initialize_cursor`` failure on a bad
HSTMT alloc), the half-initialized instance eventually hits ``__del__``.

@saurabh500

Copy link
Copy Markdown
Contributor

@subrata-ms generally looks good to me. The copilot comment on the test is interesting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-size: medium Moderate update size

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants