@@ -561,6 +561,28 @@ Overlapped_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
561
561
return (PyObject * )self ;
562
562
}
563
563
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
+
564
586
static void
565
587
Overlapped_dealloc (OverlappedObject * self )
566
588
{
@@ -594,20 +616,11 @@ Overlapped_dealloc(OverlappedObject *self)
594
616
}
595
617
}
596
618
597
- if (self -> overlapped .hEvent != NULL )
619
+ if (self -> overlapped .hEvent != NULL ) {
598
620
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 ;
610
621
}
622
+
623
+ Overlapped_clear (self );
611
624
PyObject_Del (self );
612
625
SetLastError (olderr );
613
626
}
@@ -723,8 +736,7 @@ do_ReadFile(OverlappedObject *self, HANDLE handle,
723
736
case ERROR_IO_PENDING :
724
737
Py_RETURN_NONE ;
725
738
default :
726
- PyBuffer_Release (& self -> user_buffer );
727
- self -> type = TYPE_NOT_STARTED ;
739
+ Overlapped_clear (self );
728
740
return SetFromWindowsErr (err );
729
741
}
730
742
}
@@ -827,7 +839,7 @@ do_WSARecv(OverlappedObject *self, HANDLE handle,
827
839
case ERROR_IO_PENDING :
828
840
Py_RETURN_NONE ;
829
841
default :
830
- self -> type = TYPE_NOT_STARTED ;
842
+ Overlapped_clear ( self ) ;
831
843
return SetFromWindowsErr (err );
832
844
}
833
845
}
@@ -955,7 +967,7 @@ Overlapped_WriteFile(OverlappedObject *self, PyObject *args)
955
967
case ERROR_IO_PENDING :
956
968
Py_RETURN_NONE ;
957
969
default :
958
- self -> type = TYPE_NOT_STARTED ;
970
+ Overlapped_clear ( self ) ;
959
971
return SetFromWindowsErr (err );
960
972
}
961
973
}
@@ -1012,8 +1024,7 @@ Overlapped_WSASend(OverlappedObject *self, PyObject *args)
1012
1024
case ERROR_IO_PENDING :
1013
1025
Py_RETURN_NONE ;
1014
1026
default :
1015
- PyBuffer_Release (& self -> user_buffer );
1016
- self -> type = TYPE_NOT_STARTED ;
1027
+ Overlapped_clear (self );
1017
1028
return SetFromWindowsErr (err );
1018
1029
}
1019
1030
}
@@ -1063,7 +1074,7 @@ Overlapped_AcceptEx(OverlappedObject *self, PyObject *args)
1063
1074
case ERROR_IO_PENDING :
1064
1075
Py_RETURN_NONE ;
1065
1076
default :
1066
- self -> type = TYPE_NOT_STARTED ;
1077
+ Overlapped_clear ( self ) ;
1067
1078
return SetFromWindowsErr (err );
1068
1079
}
1069
1080
}
@@ -1155,7 +1166,7 @@ Overlapped_ConnectEx(OverlappedObject *self, PyObject *args)
1155
1166
case ERROR_IO_PENDING :
1156
1167
Py_RETURN_NONE ;
1157
1168
default :
1158
- self -> type = TYPE_NOT_STARTED ;
1169
+ Overlapped_clear ( self ) ;
1159
1170
return SetFromWindowsErr (err );
1160
1171
}
1161
1172
}
@@ -1194,7 +1205,7 @@ Overlapped_DisconnectEx(OverlappedObject *self, PyObject *args)
1194
1205
case ERROR_IO_PENDING :
1195
1206
Py_RETURN_NONE ;
1196
1207
default :
1197
- self -> type = TYPE_NOT_STARTED ;
1208
+ Overlapped_clear ( self ) ;
1198
1209
return SetFromWindowsErr (err );
1199
1210
}
1200
1211
}
@@ -1249,7 +1260,7 @@ Overlapped_TransmitFile(OverlappedObject *self, PyObject *args)
1249
1260
case ERROR_IO_PENDING :
1250
1261
Py_RETURN_NONE ;
1251
1262
default :
1252
- self -> type = TYPE_NOT_STARTED ;
1263
+ Overlapped_clear ( self ) ;
1253
1264
return SetFromWindowsErr (err );
1254
1265
}
1255
1266
}
@@ -1290,7 +1301,7 @@ Overlapped_ConnectNamedPipe(OverlappedObject *self, PyObject *args)
1290
1301
case ERROR_IO_PENDING :
1291
1302
Py_RETURN_FALSE ;
1292
1303
default :
1293
- self -> type = TYPE_NOT_STARTED ;
1304
+ Overlapped_clear ( self ) ;
1294
1305
return SetFromWindowsErr (err );
1295
1306
}
1296
1307
}
@@ -1340,6 +1351,25 @@ Overlapped_getpending(OverlappedObject *self)
1340
1351
self -> type != TYPE_NOT_STARTED );
1341
1352
}
1342
1353
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
+
1343
1373
static PyMethodDef Overlapped_methods [] = {
1344
1374
{"getresult" , (PyCFunction ) Overlapped_getresult ,
1345
1375
METH_VARARGS , Overlapped_getresult_doc },
@@ -1410,7 +1440,7 @@ PyTypeObject OverlappedType = {
1410
1440
/* tp_as_buffer */ 0 ,
1411
1441
/* tp_flags */ Py_TPFLAGS_DEFAULT ,
1412
1442
/* tp_doc */ "OVERLAPPED structure wrapper" ,
1413
- /* tp_traverse */ 0 ,
1443
+ /* tp_traverse */ ( traverseproc ) Overlapped_traverse ,
1414
1444
/* tp_clear */ 0 ,
1415
1445
/* tp_richcompare */ 0 ,
1416
1446
/* tp_weaklistoffset */ 0 ,
0 commit comments