@@ -112,6 +112,20 @@ typedef struct {
112112 Py_buffer write_buffer ;
113113} OverlappedObject ;
114114
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+
115129static void
116130overlapped_dealloc (OverlappedObject * self )
117131{
@@ -150,6 +164,7 @@ overlapped_dealloc(OverlappedObject *self)
150164
151165 CloseHandle (self -> overlapped .hEvent );
152166 SetLastError (err );
167+ PyObject_GC_UnTrack (self );
153168 if (self -> write_buffer .obj )
154169 PyBuffer_Release (& self -> write_buffer );
155170 Py_CLEAR (self -> read_buffer );
@@ -321,6 +336,7 @@ static PyMemberDef overlapped_members[] = {
321336};
322337
323338static PyType_Slot winapi_overlapped_type_slots [] = {
339+ {Py_tp_traverse , overlapped_traverse },
324340 {Py_tp_dealloc , overlapped_dealloc },
325341 {Py_tp_doc , "OVERLAPPED structure wrapper" },
326342 {Py_tp_methods , overlapped_methods },
@@ -331,15 +347,16 @@ static PyType_Slot winapi_overlapped_type_slots[] = {
331347static PyType_Spec winapi_overlapped_type_spec = {
332348 .name = "_winapi.Overlapped" ,
333349 .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 ),
335352 .slots = winapi_overlapped_type_slots ,
336353};
337354
338355static OverlappedObject *
339356new_overlapped (PyObject * module , HANDLE handle )
340357{
341358 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 );
343360 if (!self )
344361 return NULL ;
345362
@@ -351,6 +368,8 @@ new_overlapped(PyObject *module, HANDLE handle)
351368 memset (& self -> write_buffer , 0 , sizeof (Py_buffer ));
352369 /* Manual reset, initially non-signalled */
353370 self -> overlapped .hEvent = CreateEvent (NULL , TRUE, FALSE, NULL );
371+
372+ PyObject_GC_Track (self );
354373 return self ;
355374}
356375
@@ -2043,12 +2062,37 @@ static PyModuleDef_Slot winapi_slots[] = {
20432062 {0 , NULL }
20442063};
20452064
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+
20462087static struct PyModuleDef winapi_module = {
20472088 PyModuleDef_HEAD_INIT ,
20482089 .m_name = "_winapi" ,
20492090 .m_size = sizeof (WinApiState ),
20502091 .m_methods = winapi_functions ,
20512092 .m_slots = winapi_slots ,
2093+ .m_traverse = winapi_traverse ,
2094+ .m_clear = winapi_clear ,
2095+ .m_free = winapi_free ,
20522096};
20532097
20542098PyMODINIT_FUNC
0 commit comments