[Python-checkins] [3.10] bpo-42972: Fully support GC for _winapi.Overlapped (GH-26381) (#26430)

pablogsal webhook-mailer at python.org
Fri May 28 13:47:26 EDT 2021


https://github.com/python/cpython/commit/0d399516320d8dfce4453037338659cef3a2adf4
commit: 0d399516320d8dfce4453037338659cef3a2adf4
branch: 3.10
author: Ken Jin <28750310+Fidget-Spinner at users.noreply.github.com>
committer: pablogsal <Pablogsal at gmail.com>
date: 2021-05-28T18:47:15+01:00
summary:

[3.10] bpo-42972: Fully support GC for _winapi.Overlapped (GH-26381)  (#26430)

* bpo-42972: Fully support GC for _winapi.Overlapped (GH-26381)

* untrack earlier

files:
M Modules/_winapi.c

diff --git a/Modules/_winapi.c b/Modules/_winapi.c
index bc2126c8e2ee99..2c034628e34e94 100644
--- a/Modules/_winapi.c
+++ b/Modules/_winapi.c
@@ -112,12 +112,27 @@ typedef struct {
     Py_buffer write_buffer;
 } OverlappedObject;
 
+/*
+Note: tp_clear (overlapped_clear) is not implemented because it
+requires cancelling the IO operation if it's pending and the cancellation is
+quite complex and can fail (see: overlapped_dealloc).
+*/
+static int
+overlapped_traverse(OverlappedObject *self, visitproc visit, void *arg)
+{
+    Py_VISIT(self->read_buffer);
+    Py_VISIT(self->write_buffer.obj);
+    Py_VISIT(Py_TYPE(self));
+    return 0;
+}
+
 static void
 overlapped_dealloc(OverlappedObject *self)
 {
     DWORD bytes;
     int err = GetLastError();
 
+    PyObject_GC_UnTrack(self);
     if (self->pending) {
         if (check_CancelIoEx() &&
             Py_CancelIoEx(self->handle, &self->overlapped) &&
@@ -321,6 +336,7 @@ static PyMemberDef overlapped_members[] = {
 };
 
 static PyType_Slot winapi_overlapped_type_slots[] = {
+    {Py_tp_traverse, overlapped_traverse},
     {Py_tp_dealloc, overlapped_dealloc},
     {Py_tp_doc, "OVERLAPPED structure wrapper"},
     {Py_tp_methods, overlapped_methods},
@@ -331,7 +347,8 @@ static PyType_Slot winapi_overlapped_type_slots[] = {
 static PyType_Spec winapi_overlapped_type_spec = {
     .name = "_winapi.Overlapped",
     .basicsize = sizeof(OverlappedObject),
-    .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
+    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
+              Py_TPFLAGS_HAVE_GC),
     .slots = winapi_overlapped_type_slots,
 };
 
@@ -339,7 +356,7 @@ static OverlappedObject *
 new_overlapped(PyObject *module, HANDLE handle)
 {
     WinApiState *st = winapi_get_state(module);
-    OverlappedObject *self = PyObject_New(OverlappedObject, st->overlapped_type);
+    OverlappedObject *self = PyObject_GC_New(OverlappedObject, st->overlapped_type);
     if (!self)
         return NULL;
 
@@ -351,6 +368,8 @@ new_overlapped(PyObject *module, HANDLE handle)
     memset(&self->write_buffer, 0, sizeof(Py_buffer));
     /* Manual reset, initially non-signalled */
     self->overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+    PyObject_GC_Track(self);
     return self;
 }
 
@@ -2043,12 +2062,37 @@ static PyModuleDef_Slot winapi_slots[] = {
     {0, NULL}
 };
 
+static int
+winapi_traverse(PyObject *module, visitproc visit, void *arg)
+{
+    WinApiState *st = winapi_get_state(module);
+    Py_VISIT(st->overlapped_type);
+    return 0;
+}
+
+static int
+winapi_clear(PyObject *module)
+{
+    WinApiState *st = winapi_get_state(module);
+    Py_CLEAR(st->overlapped_type);
+    return 0;
+}
+
+static void
+winapi_free(void *module)
+{
+    winapi_clear((PyObject *)module);
+}
+
 static struct PyModuleDef winapi_module = {
     PyModuleDef_HEAD_INIT,
     .m_name = "_winapi",
     .m_size = sizeof(WinApiState),
     .m_methods = winapi_functions,
     .m_slots = winapi_slots,
+    .m_traverse = winapi_traverse,
+    .m_clear = winapi_clear,
+    .m_free = winapi_free,
 };
 
 PyMODINIT_FUNC



More information about the Python-checkins mailing list