[3.13] gh-125243: Fix ZoneInfo data race in free threading build (GH-… · python/cpython@6474e29

GitHub

@@ -3,6 +3,7 @@

33#endif

4455#include"Python.h"

6+#include"pycore_critical_section.h"// _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED()

67#include"pycore_long.h"// _PyLong_GetOne()

78#include"pycore_pyerrors.h"// _PyErr_ChainExceptions1()

89@@ -298,15 +299,20 @@ get_weak_cache(zoneinfo_state *state, PyTypeObject *type)

298299 }

299300}

300301302+/*[clinic input]

303+@critical_section

304+@classmethod

305+zoneinfo.ZoneInfo.__new__

306+307+ key: object

308+309+Create a new ZoneInfo instance.

310+[clinic start generated code]*/

311+301312staticPyObject*

302-zoneinfo_new(PyTypeObject*type, PyObject*args, PyObject*kw)

313+zoneinfo_ZoneInfo_impl(PyTypeObject*type, PyObject*key)

314+/*[clinic end generated code: output=95e61dab86bb95c3 input=ef73d7a83bf8790e]*/

303315{

304-PyObject*key=NULL;

305-staticchar*kwlist[] = {"key", NULL};

306-if (PyArg_ParseTupleAndKeywords(args, kw, "O", kwlist, &key) ==0) {

307-returnNULL;

308- }

309-310316zoneinfo_state*state=zoneinfo_get_state_by_self(type);

311317PyObject*instance=zone_from_strong_cache(state, type, key);

312318if (instance!=NULL||PyErr_Occurred()) {

@@ -467,6 +473,7 @@ zoneinfo_ZoneInfo_no_cache_impl(PyTypeObject *type, PyTypeObject *cls,

467473}

468474469475/*[clinic input]

476+@critical_section

470477@classmethod

471478zoneinfo.ZoneInfo.clear_cache

472479@@ -481,7 +488,7 @@ Clear the ZoneInfo cache.

481488staticPyObject*

482489zoneinfo_ZoneInfo_clear_cache_impl(PyTypeObject*type, PyTypeObject*cls,

483490PyObject*only_keys)

484-/*[clinic end generated code: output=114d9b7c8a22e660 input=e32ca3bb396788ba]*/

491+/*[clinic end generated code: output=114d9b7c8a22e660 input=35944715df26d24e]*/

485492{

486493zoneinfo_state*state=zoneinfo_get_state_by_cls(cls);

487494PyObject*weak_cache=get_weak_cache(state, type);

@@ -816,14 +823,10 @@ zoneinfo_ZoneInfo__unpickle_impl(PyTypeObject *type, PyTypeObject *cls,

816823/*[clinic end generated code: output=556712fc709deecb input=6ac8c73eed3de316]*/

817824{

818825if (from_cache) {

819-PyObject*val_args=PyTuple_Pack(1, key);

820-if (val_args==NULL) {

821-returnNULL;

822- }

823-824-PyObject*rv=zoneinfo_new(type, val_args, NULL);

825-826-Py_DECREF(val_args);

826+PyObject*rv;

827+Py_BEGIN_CRITICAL_SECTION(type);

828+rv=zoneinfo_ZoneInfo_impl(type, key);

829+Py_END_CRITICAL_SECTION();

827830returnrv;

828831 }

829832else {

@@ -858,8 +861,7 @@ load_timedelta(zoneinfo_state *state, long seconds)

8588610, seconds, 0, 1, PyDateTimeAPI->DeltaType);

859862860863if (tmp!=NULL) {

861-rv=PyDict_SetDefault(state->TIMEDELTA_CACHE, pyoffset, tmp);

862-Py_XINCREF(rv);

864+PyDict_SetDefaultRef(state->TIMEDELTA_CACHE, pyoffset, tmp, &rv);

863865Py_DECREF(tmp);

864866 }

865867 }

@@ -2368,6 +2370,7 @@ strong_cache_free(StrongCacheNode *root)

23682370staticvoid

23692371remove_from_strong_cache(zoneinfo_state*state, StrongCacheNode*node)

23702372{

2373+_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(state->ZoneInfoType);

23712374if (state->ZONEINFO_STRONG_CACHE==node) {

23722375state->ZONEINFO_STRONG_CACHE=node->next;

23732376 }

@@ -2422,6 +2425,7 @@ eject_from_strong_cache(zoneinfo_state *state, const PyTypeObject *const type,

24222425return0;

24232426 }

242424272428+_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(state->ZoneInfoType);

24252429StrongCacheNode*cache=state->ZONEINFO_STRONG_CACHE;

24262430StrongCacheNode*node=find_in_strong_cache(cache, key);

24272431if (node!=NULL) {

@@ -2478,6 +2482,7 @@ zone_from_strong_cache(zoneinfo_state *state, const PyTypeObject *const type,

24782482returnNULL; // Strong cache currently only implemented for base class

24792483 }

248024842485+_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(state->ZoneInfoType);

24812486StrongCacheNode*cache=state->ZONEINFO_STRONG_CACHE;

24822487StrongCacheNode*node=find_in_strong_cache(cache, key);

24832488@@ -2504,6 +2509,7 @@ update_strong_cache(zoneinfo_state *state, const PyTypeObject *const type,

25042509return;

25052510 }

250625112512+_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(state->ZoneInfoType);

25072513StrongCacheNode*new_node=strong_cache_node_new(key, zone);

25082514if (new_node==NULL) {

25092515return;

@@ -2631,7 +2637,7 @@ static PyType_Slot zoneinfo_slots[] = {

26312637 {Py_tp_getattro, PyObject_GenericGetAttr},

26322638 {Py_tp_methods, zoneinfo_methods},

26332639 {Py_tp_members, zoneinfo_members},

2634- {Py_tp_new, zoneinfo_new},

2640+ {Py_tp_new, zoneinfo_ZoneInfo},

26352641 {Py_tp_dealloc, zoneinfo_dealloc},

26362642 {Py_tp_traverse, zoneinfo_traverse},

26372643 {Py_tp_clear, zoneinfo_clear},