File tree Expand file tree Collapse file tree
Lib/test/test_free_threading Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -268,6 +268,34 @@ def watcher():
268268 finally :
269269 _testcapi .clear_dict_watcher (wid )
270270
271+ def test_racing_split_dict_clear_and_lookup (self ):
272+ class C :
273+ pass
274+
275+ keys = [f"a{ i } " for i in range (16 )]
276+
277+ def make_split_nonembedded ():
278+ inst = C ()
279+ for key in keys :
280+ setattr (inst , key , keys .index (key ))
281+ # dict.copy() of a split instance dict yields a split table
282+ # with non-embedded values
283+ return inst .__dict__ .copy ()
284+
285+ d = make_split_nonembedded ()
286+
287+ def clearer ():
288+ for _ in range (1000 ):
289+ d .clear ()
290+ d .update (make_split_nonembedded ())
291+
292+ def reader ():
293+ for _ in range (1000 ):
294+ for k in keys :
295+ d .get (k )
296+
297+ threading_helper .run_concurrently ([clearer , reader , reader ])
298+
271299 def test_racing_dict_update_and_method_lookup (self ):
272300 # gh-144295: test race between dict modifications and method lookups.
273301 # Uses BytesIO because the race requires a type without Py_TPFLAGS_INLINE_VALUES
Original file line number Diff line number Diff line change @@ -3083,10 +3083,12 @@ clear_lock_held(PyObject *op)
30833083 set_keys (mp , Py_EMPTY_KEYS );
30843084 n = oldkeys -> dk_nentries ;
30853085 for (i = 0 ; i < n ; i ++ ) {
3086- Py_CLEAR (oldvalues -> values [i ]);
3086+ PyObject * tmp = oldvalues -> values [i ];
3087+ FT_ATOMIC_STORE_PTR_RELEASE (oldvalues -> values [i ], NULL );
3088+ Py_XDECREF (tmp );
30873089 }
30883090 free_values (oldvalues , IS_DICT_SHARED (mp ));
3089- dictkeys_decref (oldkeys , false );
3091+ dictkeys_decref (oldkeys , IS_DICT_SHARED ( mp ) );
30903092 }
30913093 ASSERT_CONSISTENT (mp );
30923094}
You can’t perform that action at this time.
0 commit comments