Skip to content

gh-108240: Fix a reference cycle in _socket.CAPI capsule #108241

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

Closed
wants to merge 1 commit into from

Conversation

vstinner
Copy link
Member

@vstinner vstinner commented Aug 21, 2023

_socket.CAPI capsule contains a strong reference to _socket.socket type. The garbage collector cannot visit this reference and so cannot create the reference cycle involving _socket.socket (a heap type creates a reference cycle to inside, via MRO and methods). At Python, _PyImport_ClearModules() sets _socket attributes to None which works around the issue.

If the module is cleared from sys.modules manually, _PyImport_ClearModules() cannot set _socket.CAPI to None and so the issue cannot be worked around.

Change _socket.CAPI to use a borrowed reference instead of a strong reference to allow clearing _socket.socket in this case.

_socket.CAPI capsule contains a strong reference to _socket.socket
type. The garbage collector cannot visit this reference and so cannot
create the reference cycle involving _socket.socket (a heap type
creates a reference cycle to inside, via MRO and methods). At Python,
_PyImport_ClearModules() sets _socket attributes to None which works
around the issue.

If the module is cleared from sys.modules manually,
_PyImport_ClearModules() cannot set _socket.CAPI to None and so the
issue cannot be worked around.

Change _socket.CAPI to use a borrowed reference instead of a strong
reference to allow clearing _socket.socket in this case.

Co-authored-by: Kirill Podoprigora <[email protected]>
@vstinner
Copy link
Member Author

Storing a borrowed reference in the capsule object is unsafe if the capsule is used after the extension is finalized. But right now, it's not possible to configure a capsule object to visit its strong references.

@vstinner
Copy link
Member Author

If we agree that this approach is the correct one, I will write a NEWS entry and backport the change to stable versions.

@vstinner
Copy link
Member Author

The PR fix the issue. Example with reproducer attached to the issue:

$ ./python -X showrefcount script.py 
exit
[0 refs, 0 blocks]

@vstinner
Copy link
Member Author

Since the _datetime capsule also uses borrowed references to types, and the _datetime capsule (C API) is more likely to be used in the wild than the _socket capsule (C API), since there is a dedicated public datetime.h C API using it. IMO it's acceptable to use borrowed references in the _socket capsule (C API).

@vstinner
Copy link
Member Author

I merged the safe approach instead: PR #108339.

@vstinner vstinner closed this Aug 23, 2023
@vstinner vstinner deleted the sock_capsule branch August 23, 2023 22:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants