From 485b16b4f7b28cefdfb524c2869d473078e349bf Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Tue, 5 Aug 2025 09:32:22 -0400 Subject: [PATCH 1/2] gh-137238: Fix data race in `_Py_slot_tp_getattr_hook` (gh-137240) Replacing the slot isn't thread-safe if the GIL is disabled. Don't require that the slot has been replaced when specializing. --- Objects/typeobject.c | 3 +++ Python/specialize.c | 9 +-------- Tools/tsan/suppressions_free_threading.txt | 1 - 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 6e67b6e01cb8b8..14bc5a4bc49f84 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -10585,7 +10585,10 @@ _Py_slot_tp_getattr_hook(PyObject *self, PyObject *name) getattr = _PyType_LookupRef(tp, &_Py_ID(__getattr__)); if (getattr == NULL) { /* No __getattr__ hook: use a simpler dispatcher */ +#ifndef Py_GIL_DISABLED + // Replacing the slot is only thread-safe if there is a GIL. tp->tp_getattro = _Py_slot_tp_getattro; +#endif return _Py_slot_tp_getattro(self, name); } /* speed hack: we could use lookup_maybe, but that would resolve the diff --git a/Python/specialize.c b/Python/specialize.c index fe8d04cf3442f1..38df5741f32520 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -935,8 +935,7 @@ analyze_descriptor_load(PyTypeObject *type, PyObject *name, PyObject **descr, un PyObject *getattr = _PyType_Lookup(type, &_Py_ID(__getattr__)); has_getattr = getattr != NULL; if (has_custom_getattribute) { - if (getattro_slot == _Py_slot_tp_getattro && - !has_getattr && + if (!has_getattr && Py_IS_TYPE(getattribute, &PyFunction_Type)) { *descr = getattribute; *tp_version = ga_version; @@ -1259,12 +1258,6 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* return -1; case GETATTRIBUTE_IS_PYTHON_FUNCTION: { - #ifndef Py_GIL_DISABLED - // In free-threaded builds it's possible for tp_getattro to change - // after the call to analyze_descriptor. That is fine: the version - // guard will fail. - assert(type->tp_getattro == _Py_slot_tp_getattro); - #endif assert(Py_IS_TYPE(descr, &PyFunction_Type)); _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1); if (!function_check_args(descr, 2, LOAD_ATTR)) { diff --git a/Tools/tsan/suppressions_free_threading.txt b/Tools/tsan/suppressions_free_threading.txt index 52d7c25a5bb37a..6bd31e8e6ecb9d 100644 --- a/Tools/tsan/suppressions_free_threading.txt +++ b/Tools/tsan/suppressions_free_threading.txt @@ -43,6 +43,5 @@ race:list_inplace_repeat_lock_held race:PyObject_Realloc # gh-133467. Some of these could be hard to trigger. -race_top:_Py_slot_tp_getattr_hook race_top:set_tp_bases race_top:type_set_bases_unlocked From 525784aa65d35a5609aba53c873a9a3a578f992b Mon Sep 17 00:00:00 2001 From: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> Date: Tue, 5 Aug 2025 16:55:05 +0200 Subject: [PATCH 2/2] gh-123441: Correct the supported languages of the iso-8859-4 codec (GH-137034) --- Doc/library/codecs.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index f96f2f8281f450..5932012c535b56 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -1251,7 +1251,7 @@ particular, the following variants typically exist: +-----------------+--------------------------------+--------------------------------+ | iso8859_3 | iso-8859-3, latin3, L3 | Esperanto, Maltese | +-----------------+--------------------------------+--------------------------------+ -| iso8859_4 | iso-8859-4, latin4, L4 | Baltic languages | +| iso8859_4 | iso-8859-4, latin4, L4 | Northern Europe | +-----------------+--------------------------------+--------------------------------+ | iso8859_5 | iso-8859-5, cyrillic | Belarusian, Bulgarian, | | | | Macedonian, Russian, Serbian |