-
Notifications
You must be signed in to change notification settings - Fork 52
FIX: prevent AttributeError in __del__ on partially-initialized Cursor #646
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
subrata-ms
wants to merge
9
commits into
main
Choose a base branch
from
subrata-ms/Bug642
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+154
−5
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
2e750de
base fix
c831f87
Merge branch 'main' into subrata-ms/Bug642
saurabh500 6fa0b63
Merge branch 'main' into subrata-ms/Bug642
subrata-ms dcb5aa4
Merge branch 'main' into subrata-ms/Bug642
subrata-ms afecb69
Potential fix for pull request finding
subrata-ms c1a3c3e
Potential fix for pull request finding
subrata-ms ae56d89
Merge branch 'main' into subrata-ms/Bug642
subrata-ms e63cf28
Merge branch 'main' into subrata-ms/Bug642
subrata-ms cd4efe0
TEST: use sys.unraisablehook to capture __del__ regressions
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this test passes even on main with the unfixed cursor.py (switched to main back in & ran this test - all green), actually it doesn't reinforce corrections done in the PR.
the unraisable from
__del__goes throughsys.unraisablehook, notwarnings, socatch_warnings(record=True)never sees it andoffendersis always empty. wrappingconn.cursor()instead (as suggested above) doesn't help, same reason.also the dealloc happens during
conn.cursor(), not thegc.collect()wrapped (_cursorsis a WeakSet).the version that breaks (fails on main, passes here):
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just rechecked the changes
this is valid for
test_cursor_init_failure_leaves_consistent_stateactually - this is a wrongly pinned comment - could you please make the changes accordingly?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're absolutely right , thanks for the careful read. Let me confirm and lay out the fix:
catch_warnings(record=True) never sees this.
Unraisable exceptions from del are routed through sys.unraisablehook, not through warnings.warn(). Pytest's builtin plugin later converts those into PytestUnraisableExceptionWarning, but that conversion runs inside pytest's own hook at capture-flush time, outside the warnings.catch_warnings block scope. So caught is empty on both fixed and unfixed cursor.py — the assertion is effectively assert not [], which is why it "passes on main". The test isn't asserting anything about the bug.
gc.collect() is the wrong sync point.
_cursors is a WeakSet, so the failed Cursor.init never installs a strong reference anywhere. When _initialize_cursor raises, the partial object's refcount hits zero the moment the exception unwinds out of conn.cursor() — del runs synchronously right there, inside the pytest.raises block. By the time gc.collect() runs, there's nothing left to collect.
The right shape of the test.
Install a sys.unraisablehook, wrap only conn.cursor() (not gc.collect()), and assert on the captured unraisable.exc_value. I verified this locally: on main (pre-fix cursor.py) that test fails with exactly the AttributeError: 'Cursor' object has no attribute 'closed' captured through the hook; on this branch it passes clean. I'll push the updated test in the next revision and drop the warnings/gc machinery entirely. Same treatment for test_cursor_del_half_initialized_cursor_no_errors — the warnings.catch_warnings block there is dead code for the same reason and should either use the unraisable hook or be removed (the c.close() call already exercises Bug A directly and would raise on unfixed code, so that assertion alone is a valid regression guard for Bug A).
Change has been pushed as part of latest commit.