mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
gh-108240: Add _PyCapsule_SetTraverse() internal function (#108339)
The _socket extension uses _PyCapsule_SetTraverse() to visit and clear the socket type in the garbage collector. So the _socket.socket type can be cleared in some corner cases when it wasn't possible before.
This commit is contained in:
parent
b6be18812c
commit
513c89d012
3 changed files with 136 additions and 73 deletions
|
@ -7314,20 +7314,39 @@ os_init(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
sock_free_api(PySocketModule_APIObject *capi)
|
||||
static int
|
||||
sock_capi_traverse(PyObject *capsule, visitproc visit, void *arg)
|
||||
{
|
||||
Py_DECREF(capi->Sock_Type);
|
||||
PySocketModule_APIObject *capi = PyCapsule_GetPointer(capsule, PySocket_CAPSULE_NAME);
|
||||
assert(capi != NULL);
|
||||
Py_VISIT(capi->Sock_Type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sock_capi_clear(PyObject *capsule)
|
||||
{
|
||||
PySocketModule_APIObject *capi = PyCapsule_GetPointer(capsule, PySocket_CAPSULE_NAME);
|
||||
assert(capi != NULL);
|
||||
Py_CLEAR(capi->Sock_Type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sock_capi_free(PySocketModule_APIObject *capi)
|
||||
{
|
||||
Py_XDECREF(capi->Sock_Type); // sock_capi_free() can clear it
|
||||
Py_DECREF(capi->error);
|
||||
Py_DECREF(capi->timeout_error);
|
||||
PyMem_Free(capi);
|
||||
}
|
||||
|
||||
static void
|
||||
sock_destroy_api(PyObject *capsule)
|
||||
sock_capi_destroy(PyObject *capsule)
|
||||
{
|
||||
void *capi = PyCapsule_GetPointer(capsule, PySocket_CAPSULE_NAME);
|
||||
sock_free_api(capi);
|
||||
assert(capi != NULL);
|
||||
sock_capi_free(capi);
|
||||
}
|
||||
|
||||
static PySocketModule_APIObject *
|
||||
|
@ -7432,11 +7451,17 @@ socket_exec(PyObject *m)
|
|||
}
|
||||
PyObject *capsule = PyCapsule_New(capi,
|
||||
PySocket_CAPSULE_NAME,
|
||||
sock_destroy_api);
|
||||
sock_capi_destroy);
|
||||
if (capsule == NULL) {
|
||||
sock_free_api(capi);
|
||||
sock_capi_free(capi);
|
||||
goto error;
|
||||
}
|
||||
if (_PyCapsule_SetTraverse(capsule,
|
||||
sock_capi_traverse, sock_capi_clear) < 0) {
|
||||
sock_capi_free(capi);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (PyModule_Add(m, PySocket_CAPI_NAME, capsule) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue