@@ -561,6 +561,28 @@ Overlapped_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
561561 return (PyObject * )self ;
562562}
563563
564+
565+ /* Note (bpo-32710): OverlappedType.tp_clear is not defined to not release
566+ buffers while overlapped are still running, to prevent a crash. */
567+ static int
568+ Overlapped_clear (OverlappedObject * self )
569+ {
570+ switch (self -> type ) {
571+ case TYPE_READ :
572+ case TYPE_ACCEPT :
573+ Py_CLEAR (self -> allocated_buffer );
574+ break ;
575+ case TYPE_WRITE :
576+ case TYPE_READINTO :
577+ if (self -> user_buffer .obj ) {
578+ PyBuffer_Release (& self -> user_buffer );
579+ }
580+ break ;
581+ }
582+ self -> type = TYPE_NOT_STARTED ;
583+ return 0 ;
584+ }
585+
564586static void
565587Overlapped_dealloc (OverlappedObject * self )
566588{
@@ -594,20 +616,11 @@ Overlapped_dealloc(OverlappedObject *self)
594616 }
595617 }
596618
597- if (self -> overlapped .hEvent != NULL )
619+ if (self -> overlapped .hEvent != NULL ) {
598620 CloseHandle (self -> overlapped .hEvent );
599-
600- switch (self -> type ) {
601- case TYPE_READ :
602- case TYPE_ACCEPT :
603- Py_CLEAR (self -> allocated_buffer );
604- break ;
605- case TYPE_WRITE :
606- case TYPE_READINTO :
607- if (self -> user_buffer .obj )
608- PyBuffer_Release (& self -> user_buffer );
609- break ;
610621 }
622+
623+ Overlapped_clear (self );
611624 PyObject_Del (self );
612625 SetLastError (olderr );
613626}
@@ -723,8 +736,7 @@ do_ReadFile(OverlappedObject *self, HANDLE handle,
723736 case ERROR_IO_PENDING :
724737 Py_RETURN_NONE ;
725738 default :
726- PyBuffer_Release (& self -> user_buffer );
727- self -> type = TYPE_NOT_STARTED ;
739+ Overlapped_clear (self );
728740 return SetFromWindowsErr (err );
729741 }
730742}
@@ -827,7 +839,7 @@ do_WSARecv(OverlappedObject *self, HANDLE handle,
827839 case ERROR_IO_PENDING :
828840 Py_RETURN_NONE ;
829841 default :
830- self -> type = TYPE_NOT_STARTED ;
842+ Overlapped_clear ( self ) ;
831843 return SetFromWindowsErr (err );
832844 }
833845}
@@ -955,7 +967,7 @@ Overlapped_WriteFile(OverlappedObject *self, PyObject *args)
955967 case ERROR_IO_PENDING :
956968 Py_RETURN_NONE ;
957969 default :
958- self -> type = TYPE_NOT_STARTED ;
970+ Overlapped_clear ( self ) ;
959971 return SetFromWindowsErr (err );
960972 }
961973}
@@ -1012,8 +1024,7 @@ Overlapped_WSASend(OverlappedObject *self, PyObject *args)
10121024 case ERROR_IO_PENDING :
10131025 Py_RETURN_NONE ;
10141026 default :
1015- PyBuffer_Release (& self -> user_buffer );
1016- self -> type = TYPE_NOT_STARTED ;
1027+ Overlapped_clear (self );
10171028 return SetFromWindowsErr (err );
10181029 }
10191030}
@@ -1063,7 +1074,7 @@ Overlapped_AcceptEx(OverlappedObject *self, PyObject *args)
10631074 case ERROR_IO_PENDING :
10641075 Py_RETURN_NONE ;
10651076 default :
1066- self -> type = TYPE_NOT_STARTED ;
1077+ Overlapped_clear ( self ) ;
10671078 return SetFromWindowsErr (err );
10681079 }
10691080}
@@ -1155,7 +1166,7 @@ Overlapped_ConnectEx(OverlappedObject *self, PyObject *args)
11551166 case ERROR_IO_PENDING :
11561167 Py_RETURN_NONE ;
11571168 default :
1158- self -> type = TYPE_NOT_STARTED ;
1169+ Overlapped_clear ( self ) ;
11591170 return SetFromWindowsErr (err );
11601171 }
11611172}
@@ -1194,7 +1205,7 @@ Overlapped_DisconnectEx(OverlappedObject *self, PyObject *args)
11941205 case ERROR_IO_PENDING :
11951206 Py_RETURN_NONE ;
11961207 default :
1197- self -> type = TYPE_NOT_STARTED ;
1208+ Overlapped_clear ( self ) ;
11981209 return SetFromWindowsErr (err );
11991210 }
12001211}
@@ -1249,7 +1260,7 @@ Overlapped_TransmitFile(OverlappedObject *self, PyObject *args)
12491260 case ERROR_IO_PENDING :
12501261 Py_RETURN_NONE ;
12511262 default :
1252- self -> type = TYPE_NOT_STARTED ;
1263+ Overlapped_clear ( self ) ;
12531264 return SetFromWindowsErr (err );
12541265 }
12551266}
@@ -1290,7 +1301,7 @@ Overlapped_ConnectNamedPipe(OverlappedObject *self, PyObject *args)
12901301 case ERROR_IO_PENDING :
12911302 Py_RETURN_FALSE ;
12921303 default :
1293- self -> type = TYPE_NOT_STARTED ;
1304+ Overlapped_clear ( self ) ;
12941305 return SetFromWindowsErr (err );
12951306 }
12961307}
@@ -1340,6 +1351,25 @@ Overlapped_getpending(OverlappedObject *self)
13401351 self -> type != TYPE_NOT_STARTED );
13411352}
13421353
1354+ static int
1355+ Overlapped_traverse (OverlappedObject * self , visitproc visit , void * arg )
1356+ {
1357+ switch (self -> type ) {
1358+ case TYPE_READ :
1359+ case TYPE_ACCEPT :
1360+ Py_VISIT (self -> allocated_buffer );
1361+ break ;
1362+ case TYPE_WRITE :
1363+ case TYPE_READINTO :
1364+ if (self -> user_buffer .obj ) {
1365+ Py_VISIT (& self -> user_buffer .obj );
1366+ }
1367+ break ;
1368+ }
1369+ return 0 ;
1370+ }
1371+
1372+
13431373static PyMethodDef Overlapped_methods [] = {
13441374 {"getresult" , (PyCFunction ) Overlapped_getresult ,
13451375 METH_VARARGS , Overlapped_getresult_doc },
@@ -1410,7 +1440,7 @@ PyTypeObject OverlappedType = {
14101440 /* tp_as_buffer */ 0 ,
14111441 /* tp_flags */ Py_TPFLAGS_DEFAULT ,
14121442 /* tp_doc */ "OVERLAPPED structure wrapper" ,
1413- /* tp_traverse */ 0 ,
1443+ /* tp_traverse */ ( traverseproc ) Overlapped_traverse ,
14141444 /* tp_clear */ 0 ,
14151445 /* tp_richcompare */ 0 ,
14161446 /* tp_weaklistoffset */ 0 ,
0 commit comments