diff options
author | Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> | 2021-05-28 17:47:15 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-28 17:47:15 (GMT) |
commit | 0d399516320d8dfce4453037338659cef3a2adf4 (patch) | |
tree | 9ffc79dc0d71753ff98e754f03122caf1ba4e901 /Modules | |
parent | 1c0106ca8c72d671ad4e2b553489d786d06fce03 (diff) | |
download | cpython-0d399516320d8dfce4453037338659cef3a2adf4.zip cpython-0d399516320d8dfce4453037338659cef3a2adf4.tar.gz cpython-0d399516320d8dfce4453037338659cef3a2adf4.tar.bz2 |
[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
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_winapi.c | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/Modules/_winapi.c b/Modules/_winapi.c index bc2126c..2c03462 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 |