@@ -112,12 +112,27 @@ typedef struct {
112
112
Py_buffer write_buffer ;
113
113
} OverlappedObject ;
114
114
115
+ /*
116
+ Note: tp_clear (overlapped_clear) is not implemented because it
117
+ requires cancelling the IO operation if it's pending and the cancellation is
118
+ quite complex and can fail (see: overlapped_dealloc).
119
+ */
120
+ static int
121
+ overlapped_traverse (OverlappedObject * self , visitproc visit , void * arg )
122
+ {
123
+ Py_VISIT (self -> read_buffer );
124
+ Py_VISIT (self -> write_buffer .obj );
125
+ Py_VISIT (Py_TYPE (self ));
126
+ return 0 ;
127
+ }
128
+
115
129
static void
116
130
overlapped_dealloc (OverlappedObject * self )
117
131
{
118
132
DWORD bytes ;
119
133
int err = GetLastError ();
120
134
135
+ PyObject_GC_UnTrack (self );
121
136
if (self -> pending ) {
122
137
if (check_CancelIoEx () &&
123
138
Py_CancelIoEx (self -> handle , & self -> overlapped ) &&
@@ -321,6 +336,7 @@ static PyMemberDef overlapped_members[] = {
321
336
};
322
337
323
338
static PyType_Slot winapi_overlapped_type_slots [] = {
339
+ {Py_tp_traverse , overlapped_traverse },
324
340
{Py_tp_dealloc , overlapped_dealloc },
325
341
{Py_tp_doc , "OVERLAPPED structure wrapper" },
326
342
{Py_tp_methods , overlapped_methods },
@@ -331,15 +347,16 @@ static PyType_Slot winapi_overlapped_type_slots[] = {
331
347
static PyType_Spec winapi_overlapped_type_spec = {
332
348
.name = "_winapi.Overlapped" ,
333
349
.basicsize = sizeof (OverlappedObject ),
334
- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION ,
350
+ .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
351
+ Py_TPFLAGS_HAVE_GC ),
335
352
.slots = winapi_overlapped_type_slots ,
336
353
};
337
354
338
355
static OverlappedObject *
339
356
new_overlapped (PyObject * module , HANDLE handle )
340
357
{
341
358
WinApiState * st = winapi_get_state (module );
342
- OverlappedObject * self = PyObject_New (OverlappedObject , st -> overlapped_type );
359
+ OverlappedObject * self = PyObject_GC_New (OverlappedObject , st -> overlapped_type );
343
360
if (!self )
344
361
return NULL ;
345
362
@@ -351,6 +368,8 @@ new_overlapped(PyObject *module, HANDLE handle)
351
368
memset (& self -> write_buffer , 0 , sizeof (Py_buffer ));
352
369
/* Manual reset, initially non-signalled */
353
370
self -> overlapped .hEvent = CreateEvent (NULL , TRUE, FALSE, NULL );
371
+
372
+ PyObject_GC_Track (self );
354
373
return self ;
355
374
}
356
375
@@ -2043,12 +2062,37 @@ static PyModuleDef_Slot winapi_slots[] = {
2043
2062
{0 , NULL }
2044
2063
};
2045
2064
2065
+ static int
2066
+ winapi_traverse (PyObject * module , visitproc visit , void * arg )
2067
+ {
2068
+ WinApiState * st = winapi_get_state (module );
2069
+ Py_VISIT (st -> overlapped_type );
2070
+ return 0 ;
2071
+ }
2072
+
2073
+ static int
2074
+ winapi_clear (PyObject * module )
2075
+ {
2076
+ WinApiState * st = winapi_get_state (module );
2077
+ Py_CLEAR (st -> overlapped_type );
2078
+ return 0 ;
2079
+ }
2080
+
2081
+ static void
2082
+ winapi_free (void * module )
2083
+ {
2084
+ winapi_clear ((PyObject * )module );
2085
+ }
2086
+
2046
2087
static struct PyModuleDef winapi_module = {
2047
2088
PyModuleDef_HEAD_INIT ,
2048
2089
.m_name = "_winapi" ,
2049
2090
.m_size = sizeof (WinApiState ),
2050
2091
.m_methods = winapi_functions ,
2051
2092
.m_slots = winapi_slots ,
2093
+ .m_traverse = winapi_traverse ,
2094
+ .m_clear = winapi_clear ,
2095
+ .m_free = winapi_free ,
2052
2096
};
2053
2097
2054
2098
PyMODINIT_FUNC
0 commit comments