File tree Expand file tree Collapse file tree 32 files changed +77
-83
lines changed
Misc/NEWS.d/next/Core_and_Builtins Expand file tree Collapse file tree 32 files changed +77
-83
lines changed Original file line number Diff line number Diff line change @@ -29,6 +29,12 @@ extern "C" {
29
29
PyMutex_LockFlags(wr->weakrefs_lock, _Py_LOCK_DONT_DETACH)
30
30
#define UNLOCK_WEAKREFS_FOR_WR (wr ) PyMutex_Unlock(wr->weakrefs_lock)
31
31
32
+ #define FT_CLEAR_WEAKREFS (obj , weakref_list ) \
33
+ do { \
34
+ assert(Py_REFCNT(obj) == 0); \
35
+ PyObject_ClearWeakRefs(obj); \
36
+ } while (0)
37
+
32
38
#else
33
39
34
40
#define LOCK_WEAKREFS (obj )
@@ -37,6 +43,14 @@ extern "C" {
37
43
#define LOCK_WEAKREFS_FOR_WR (wr )
38
44
#define UNLOCK_WEAKREFS_FOR_WR (wr )
39
45
46
+ #define FT_CLEAR_WEAKREFS (obj , weakref_list ) \
47
+ do { \
48
+ assert(Py_REFCNT(obj) == 0); \
49
+ if (weakref_list != NULL) { \
50
+ PyObject_ClearWeakRefs(obj); \
51
+ } \
52
+ } while (0)
53
+
40
54
#endif
41
55
42
56
static inline int _is_dead (PyObject * obj )
Original file line number Diff line number Diff line change
1
+ Fix potential :mod: `weakref ` races in an object's destructor on the :term: `free threaded <free
2
+ threading> ` build.
Original file line number Diff line number Diff line change 5
5
#include "pycore_moduleobject.h" // _PyModule_GetState()
6
6
#include "pycore_pyatomic_ft_wrappers.h"
7
7
#include "pycore_typeobject.h" // _PyType_GetModuleState()
8
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
8
9
9
10
#include <stddef.h>
10
11
@@ -1532,9 +1533,7 @@ deque_dealloc(PyObject *self)
1532
1533
Py_ssize_t i ;
1533
1534
1534
1535
PyObject_GC_UnTrack (deque );
1535
- if (deque -> weakreflist != NULL ) {
1536
- PyObject_ClearWeakRefs (self );
1537
- }
1536
+ FT_CLEAR_WEAKREFS (self , deque -> weakreflist );
1538
1537
if (deque -> leftblock != NULL ) {
1539
1538
(void )deque_clear (self );
1540
1539
assert (deque -> leftblock != NULL );
Original file line number Diff line number Diff line change 17
17
18
18
#include "Python.h"
19
19
#include "pycore_pyhash.h" // _Py_HashSecret
20
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
20
21
21
22
#include <stddef.h> // offsetof()
22
23
#include "expat.h"
@@ -690,8 +691,7 @@ element_dealloc(PyObject *op)
690
691
/* bpo-31095: UnTrack is needed before calling any callbacks */
691
692
PyObject_GC_UnTrack (self );
692
693
693
- if (self -> weakreflist != NULL )
694
- PyObject_ClearWeakRefs (op );
694
+ FT_CLEAR_WEAKREFS (op , self -> weakreflist );
695
695
696
696
/* element_gc_clear clears all references and deallocates extra
697
697
*/
Original file line number Diff line number Diff line change 7
7
#include "pycore_pyatomic_ft_wrappers.h"
8
8
#include "pycore_pystate.h" // _PyThreadState_GET()
9
9
#include "pycore_tuple.h" // _PyTuple_ITEMS()
10
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
10
11
11
12
12
13
#include "clinic/_functoolsmodule.c.h"
@@ -351,9 +352,7 @@ partial_dealloc(PyObject *self)
351
352
PyTypeObject * tp = Py_TYPE (self );
352
353
/* bpo-31095: UnTrack is needed before calling any callbacks */
353
354
PyObject_GC_UnTrack (self );
354
- if (partialobject_CAST (self )-> weakreflist != NULL ) {
355
- PyObject_ClearWeakRefs (self );
356
- }
355
+ FT_CLEAR_WEAKREFS (self , partialobject_CAST (self )-> weakreflist );
357
356
(void )partial_clear (self );
358
357
tp -> tp_free (self );
359
358
Py_DECREF (tp );
@@ -1621,9 +1620,7 @@ lru_cache_dealloc(PyObject *op)
1621
1620
PyTypeObject * tp = Py_TYPE (obj );
1622
1621
/* bpo-31095: UnTrack is needed before calling any callbacks */
1623
1622
PyObject_GC_UnTrack (obj );
1624
- if (obj -> weakreflist != NULL ) {
1625
- PyObject_ClearWeakRefs (op );
1626
- }
1623
+ FT_CLEAR_WEAKREFS (op , obj -> weakreflist );
1627
1624
1628
1625
(void )lru_cache_tp_clear (op );
1629
1626
tp -> tp_free (obj );
Original file line number Diff line number Diff line change 13
13
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
14
14
#include "pycore_pyerrors.h" // _Py_FatalErrorFormat()
15
15
#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()
16
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
16
17
17
18
#include "_iomodule.h"
18
19
@@ -421,8 +422,7 @@ buffered_dealloc(PyObject *op)
421
422
return ;
422
423
_PyObject_GC_UNTRACK (self );
423
424
self -> ok = 0 ;
424
- if (self -> weakreflist != NULL )
425
- PyObject_ClearWeakRefs (op );
425
+ FT_CLEAR_WEAKREFS (op , self -> weakreflist );
426
426
if (self -> buffer ) {
427
427
PyMem_Free (self -> buffer );
428
428
self -> buffer = NULL ;
@@ -2312,8 +2312,7 @@ bufferedrwpair_dealloc(PyObject *op)
2312
2312
rwpair * self = rwpair_CAST (op );
2313
2313
PyTypeObject * tp = Py_TYPE (self );
2314
2314
_PyObject_GC_UNTRACK (self );
2315
- if (self -> weakreflist != NULL )
2316
- PyObject_ClearWeakRefs (op );
2315
+ FT_CLEAR_WEAKREFS (op , self -> weakreflist );
2317
2316
(void )bufferedrwpair_clear (op );
2318
2317
tp -> tp_free (self );
2319
2318
Py_DECREF (tp );
Original file line number Diff line number Diff line change 3
3
#include "pycore_object.h"
4
4
#include "pycore_pyatomic_ft_wrappers.h"
5
5
#include "pycore_sysmodule.h" // _PySys_GetSizeOf()
6
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
6
7
7
8
#include <stddef.h> // offsetof()
8
9
#include "_iomodule.h"
@@ -979,8 +980,7 @@ bytesio_dealloc(PyObject *op)
979
980
}
980
981
Py_CLEAR (self -> buf );
981
982
Py_CLEAR (self -> dict );
982
- if (self -> weakreflist != NULL )
983
- PyObject_ClearWeakRefs (op );
983
+ FT_CLEAR_WEAKREFS (op , self -> weakreflist );
984
984
tp -> tp_free (self );
985
985
Py_DECREF (tp );
986
986
}
Original file line number Diff line number Diff line change 4
4
#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
5
5
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
6
6
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
7
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
7
8
8
9
#include <stdbool.h> // bool
9
10
#ifdef HAVE_UNISTD_H
@@ -570,9 +571,7 @@ fileio_dealloc(PyObject *op)
570
571
PyMem_Free (self -> stat_atopen );
571
572
self -> stat_atopen = NULL ;
572
573
}
573
- if (self -> weakreflist != NULL ) {
574
- PyObject_ClearWeakRefs (op );
575
- }
574
+ FT_CLEAR_WEAKREFS (op , self -> weakreflist );
576
575
(void )fileio_clear (op );
577
576
578
577
PyTypeObject * tp = Py_TYPE (op );
Original file line number Diff line number Diff line change 14
14
#include "pycore_long.h" // _PyLong_GetOne()
15
15
#include "pycore_object.h" // _PyType_HasFeature()
16
16
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
17
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
17
18
18
19
#include <stddef.h> // offsetof()
19
20
#include "_iomodule.h"
@@ -383,8 +384,7 @@ iobase_dealloc(PyObject *op)
383
384
}
384
385
PyTypeObject * tp = Py_TYPE (self );
385
386
_PyObject_GC_UNTRACK (self );
386
- if (self -> weakreflist != NULL )
387
- PyObject_ClearWeakRefs (op );
387
+ FT_CLEAR_WEAKREFS (op , self -> weakreflist );
388
388
Py_CLEAR (self -> dict );
389
389
tp -> tp_free (self );
390
390
Py_DECREF (tp );
Original file line number Diff line number Diff line change 1
1
#include "Python.h"
2
2
#include <stddef.h> // offsetof()
3
3
#include "pycore_object.h"
4
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
4
5
#include "_iomodule.h"
5
6
6
7
/* Implementation note: the buffer is always at least one character longer
@@ -638,9 +639,7 @@ stringio_dealloc(PyObject *op)
638
639
}
639
640
PyUnicodeWriter_Discard (self -> writer );
640
641
(void )stringio_clear (op );
641
- if (self -> weakreflist != NULL ) {
642
- PyObject_ClearWeakRefs (op );
643
- }
642
+ FT_CLEAR_WEAKREFS (op , self -> weakreflist );
644
643
tp -> tp_free (self );
645
644
Py_DECREF (tp );
646
645
}
Original file line number Diff line number Diff line change 16
16
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
17
17
#include "pycore_pystate.h" // _PyInterpreterState_GET()
18
18
#include "pycore_unicodeobject.h" // _PyUnicode_AsASCIIString()
19
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
19
20
20
21
#include "_iomodule.h"
21
22
@@ -1469,8 +1470,7 @@ textiowrapper_dealloc(PyObject *op)
1469
1470
return ;
1470
1471
self -> ok = 0 ;
1471
1472
_PyObject_GC_UNTRACK (self );
1472
- if (self -> weakreflist != NULL )
1473
- PyObject_ClearWeakRefs (op );
1473
+ FT_CLEAR_WEAKREFS (op , self -> weakreflist );
1474
1474
(void )textiowrapper_clear (op );
1475
1475
tp -> tp_free (self );
1476
1476
Py_DECREF (tp );
Original file line number Diff line number Diff line change 10
10
#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
11
11
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
12
12
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
13
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
13
14
14
15
#ifdef HAVE_WINDOWS_CONSOLE_IO
15
16
@@ -518,8 +519,7 @@ winconsoleio_dealloc(PyObject *op)
518
519
if (_PyIOBase_finalize (op ) < 0 )
519
520
return ;
520
521
_PyObject_GC_UNTRACK (self );
521
- if (self -> weakreflist != NULL )
522
- PyObject_ClearWeakRefs (op );
522
+ FT_CLEAR_WEAKREFS (op , self -> weakreflist );
523
523
Py_CLEAR (self -> dict );
524
524
tp -> tp_free (self );
525
525
Py_DECREF (tp );
Original file line number Diff line number Diff line change 7
7
#include "pycore_moduleobject.h" // _PyModule_GetState()
8
8
#include "pycore_parking_lot.h"
9
9
#include "pycore_time.h" // _PyTime_FromSecondsObject()
10
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
10
11
11
12
#include <stdbool.h>
12
13
#include <stddef.h> // offsetof()
@@ -221,9 +222,7 @@ simplequeue_dealloc(PyObject *op)
221
222
222
223
PyObject_GC_UnTrack (self );
223
224
(void )simplequeue_clear (op );
224
- if (self -> weakreflist != NULL ) {
225
- PyObject_ClearWeakRefs (op );
226
- }
225
+ FT_CLEAR_WEAKREFS (op , self -> weakreflist );
227
226
tp -> tp_free (self );
228
227
Py_DECREF (tp );
229
228
}
Original file line number Diff line number Diff line change 4
4
5
5
#include "blob.h"
6
6
#include "util.h"
7
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
7
8
8
9
#define clinic_state () (pysqlite_get_state_by_type(Py_TYPE(self)))
9
10
#include "clinic/blob.c.h"
@@ -56,9 +57,7 @@ blob_dealloc(PyObject *op)
56
57
57
58
close_blob (self );
58
59
59
- if (self -> in_weakreflist != NULL ) {
60
- PyObject_ClearWeakRefs (op );
61
- }
60
+ FT_CLEAR_WEAKREFS (op , self -> in_weakreflist );
62
61
(void )tp -> tp_clear (op );
63
62
tp -> tp_free (self );
64
63
Py_DECREF (tp );
Original file line number Diff line number Diff line change 31
31
#include "util.h"
32
32
33
33
#include "pycore_pyerrors.h" // _PyErr_FormatFromCause()
34
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
34
35
35
36
typedef enum {
36
37
TYPE_LONG ,
@@ -185,9 +186,7 @@ cursor_dealloc(PyObject *op)
185
186
pysqlite_Cursor * self = _pysqlite_Cursor_CAST (op );
186
187
PyTypeObject * tp = Py_TYPE (self );
187
188
PyObject_GC_UnTrack (self );
188
- if (self -> in_weakreflist != NULL ) {
189
- PyObject_ClearWeakRefs (op );
190
- }
189
+ FT_CLEAR_WEAKREFS (op , self -> in_weakreflist );
191
190
(void )tp -> tp_clear (op );
192
191
tp -> tp_free (self );
193
192
Py_DECREF (tp );
Original file line number Diff line number Diff line change @@ -44,6 +44,7 @@ static const char copyright[] =
44
44
#include "pycore_long.h" // _PyLong_GetZero()
45
45
#include "pycore_moduleobject.h" // _PyModule_GetState()
46
46
#include "pycore_unicodeobject.h" // _PyUnicode_Copy
47
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
47
48
48
49
#include "sre.h" // SRE_CODE
49
50
@@ -736,10 +737,7 @@ pattern_dealloc(PyObject *self)
736
737
{
737
738
PyTypeObject * tp = Py_TYPE (self );
738
739
PyObject_GC_UnTrack (self );
739
- PatternObject * obj = _PatternObject_CAST (self );
740
- if (obj -> weakreflist != NULL ) {
741
- PyObject_ClearWeakRefs (self );
742
- }
740
+ FT_CLEAR_WEAKREFS (self , _PatternObject_CAST (self )-> weakreflist );
743
741
(void )pattern_clear (self );
744
742
tp -> tp_free (self );
745
743
Py_DECREF (tp );
Original file line number Diff line number Diff line change 11
11
#include "pycore_bytesobject.h" // _PyBytesWriter
12
12
#include "pycore_long.h" // _PyLong_AsByteArray()
13
13
#include "pycore_moduleobject.h" // _PyModule_GetState()
14
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
14
15
15
16
#include <stddef.h> // offsetof()
16
17
@@ -1794,9 +1795,7 @@ s_dealloc(PyObject *op)
1794
1795
PyStructObject * s = PyStructObject_CAST (op );
1795
1796
PyTypeObject * tp = Py_TYPE (s );
1796
1797
PyObject_GC_UnTrack (s );
1797
- if (s -> weakreflist != NULL ) {
1798
- PyObject_ClearWeakRefs (op );
1799
- }
1798
+ FT_CLEAR_WEAKREFS (op , s -> weakreflist );
1800
1799
if (s -> s_codes != NULL ) {
1801
1800
PyMem_Free (s -> s_codes );
1802
1801
}
Original file line number Diff line number Diff line change @@ -1365,9 +1365,7 @@ static void
1365
1365
localdummy_dealloc (PyObject * op )
1366
1366
{
1367
1367
localdummyobject * self = localdummyobject_CAST (op );
1368
- if (self -> weakreflist != NULL ) {
1369
- PyObject_ClearWeakRefs (op );
1370
- }
1368
+ FT_CLEAR_WEAKREFS (op , self -> weakreflist );
1371
1369
PyTypeObject * tp = Py_TYPE (self );
1372
1370
tp -> tp_free (self );
1373
1371
Py_DECREF (tp );
Original file line number Diff line number Diff line change 7
7
#include "pycore_long.h" // _PyLong_GetOne()
8
8
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
9
9
#include "pycore_typeobject.h" // _PyType_GetModuleState()
10
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
10
11
11
12
#include "datetime.h" // PyDateTime_TZInfo
12
13
@@ -375,9 +376,7 @@ zoneinfo_dealloc(PyObject *obj_self)
375
376
PyTypeObject * tp = Py_TYPE (self );
376
377
PyObject_GC_UnTrack (self );
377
378
378
- if (self -> weakreflist != NULL ) {
379
- PyObject_ClearWeakRefs (obj_self );
380
- }
379
+ FT_CLEAR_WEAKREFS (obj_self , self -> weakreflist );
381
380
382
381
if (self -> trans_list_utc != NULL ) {
383
382
PyMem_Free (self -> trans_list_utc );
Original file line number Diff line number Diff line change 13
13
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
14
14
#include "pycore_modsupport.h" // _PyArg_NoKeywords()
15
15
#include "pycore_moduleobject.h" // _PyModule_GetState()
16
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
16
17
17
18
#include <stddef.h> // offsetof()
18
19
#include <stdbool.h>
@@ -728,9 +729,7 @@ array_dealloc(PyObject *op)
728
729
PyObject_GC_UnTrack (op );
729
730
730
731
arrayobject * self = arrayobject_CAST (op );
731
- if (self -> weakreflist != NULL ) {
732
- PyObject_ClearWeakRefs (op );
733
- }
732
+ FT_CLEAR_WEAKREFS (op , self -> weakreflist );
734
733
if (self -> ob_item != NULL ) {
735
734
PyMem_Free (self -> ob_item );
736
735
}
Original file line number Diff line number Diff line change 25
25
#include <Python.h>
26
26
#include "pycore_bytesobject.h" // _PyBytes_Find()
27
27
#include "pycore_fileutils.h" // _Py_stat_struct
28
+ #include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
28
29
29
30
#include <stddef.h> // offsetof()
30
31
#ifndef MS_WINDOWS
@@ -163,8 +164,7 @@ mmap_object_dealloc(PyObject *op)
163
164
Py_END_ALLOW_THREADS
164
165
#endif /* UNIX */
165
166
166
- if (m_obj -> weakreflist != NULL )
167
- PyObject_ClearWeakRefs (op );
167
+ FT_CLEAR_WEAKREFS (op , m_obj -> weakreflist );
168
168
169
169
tp -> tp_free (m_obj );
170
170
Py_DECREF (tp );
You can’t perform that action at this time.
0 commit comments