From 6cb88977e006ec426daa823921739e12620ac64c Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sun, 14 Jul 2024 17:34:24 +0800 Subject: [PATCH 1/6] Fix races in tracebacks --- Objects/exceptions.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 6376f2f012a7d6..e0925190993386 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -308,7 +308,7 @@ BaseException_set_args(PyBaseExceptionObject *self, PyObject *val, void *Py_UNUS } static PyObject * -BaseException_get_tb(PyBaseExceptionObject *self, void *Py_UNUSED(ignored)) +BaseException_get_tb_lock_held(PyBaseExceptionObject *self, void *Py_UNUSED(ignored)) { if (self->traceback == NULL) { Py_RETURN_NONE; @@ -316,8 +316,18 @@ BaseException_get_tb(PyBaseExceptionObject *self, void *Py_UNUSED(ignored)) return Py_NewRef(self->traceback); } +static PyObject * +BaseException_get_tb(PyBaseExceptionObject *self, void *Py_UNUSED(ignored)) +{ + PyObject *res; + Py_BEGIN_CRITICAL_SECTION(self); + res = BaseException_get_tb_lock_held(self, NULL); + Py_END_CRITICAL_SECTION(); + return res; +} + static int -BaseException_set_tb(PyBaseExceptionObject *self, PyObject *tb, void *Py_UNUSED(ignored)) +BaseException_set_tb_lock_held(PyBaseExceptionObject *self, PyObject *tb, void *Py_UNUSED(ignored)) { if (tb == NULL) { PyErr_SetString(PyExc_TypeError, "__traceback__ may not be deleted"); @@ -337,6 +347,16 @@ BaseException_set_tb(PyBaseExceptionObject *self, PyObject *tb, void *Py_UNUSED( return 0; } +static int +BaseException_set_tb(PyBaseExceptionObject *self, PyObject *tb, void *Py_UNUSED(ignored)) +{ + int res; + Py_BEGIN_CRITICAL_SECTION(self); + res = BaseException_set_tb_lock_held(self, tb, NULL); + Py_END_CRITICAL_SECTION(); + return res; +} + static PyObject * BaseException_get_context(PyObject *self, void *Py_UNUSED(ignored)) { From 5bc855c165947e9e7a4a231c65c96f754392ef54 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sun, 14 Jul 2024 17:41:28 +0800 Subject: [PATCH 2/6] use atomics in new_reference --- Objects/object.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Objects/object.c b/Objects/object.c index c4622359bb1035..eb72d58858ecaf 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -2364,8 +2364,8 @@ new_reference(PyObject *op) op->_padding = 0; op->ob_mutex = (PyMutex){ 0 }; op->ob_gc_bits = 0; - op->ob_ref_local = 1; - op->ob_ref_shared = 0; + _Py_atomic_store_uint32_release(&op->ob_ref_local, 1); + _Py_atomic_store_ssize_release(&op->ob_ref_shared, 0); #endif #ifdef Py_TRACE_REFS _Py_AddToAllObjects(op); From da8415dee9fd519cd8fa9f2c6f6cad75c8d91ab0 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sun, 14 Jul 2024 17:50:23 +0800 Subject: [PATCH 3/6] Add more atomics --- Include/cpython/pyatomic_gcc.h | 4 ++++ Include/cpython/pyatomic_msc.h | 13 +++++++++++++ Include/cpython/pyatomic_std.h | 8 ++++++++ Objects/object.c | 4 ++-- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Include/cpython/pyatomic_gcc.h b/Include/cpython/pyatomic_gcc.h index ef09954d53ac1d..975bf9f988ae2e 100644 --- a/Include/cpython/pyatomic_gcc.h +++ b/Include/cpython/pyatomic_gcc.h @@ -516,6 +516,10 @@ static inline int _Py_atomic_load_int_acquire(const int *obj) { return __atomic_load_n(obj, __ATOMIC_ACQUIRE); } +static inline void +_Py_atomic_store_uint8_release(uint8_t *obj, uint8_t value) +{ __atomic_store_n(obj, value, __ATOMIC_RELEASE); } + static inline void _Py_atomic_store_uint32_release(uint32_t *obj, uint32_t value) { __atomic_store_n(obj, value, __ATOMIC_RELEASE); } diff --git a/Include/cpython/pyatomic_msc.h b/Include/cpython/pyatomic_msc.h index 84da21bdcbff4f..4c52f043fed99d 100644 --- a/Include/cpython/pyatomic_msc.h +++ b/Include/cpython/pyatomic_msc.h @@ -989,6 +989,19 @@ _Py_atomic_load_int_acquire(const int *obj) #endif } +static inline void +_Py_atomic_store_uint8_release(uint8_t *obj, uint8_t value) +{ +#if defined(_M_X64) || defined(_M_IX86) + *(uint8_t volatile *)obj = value; +#elif defined(_M_ARM64) + _Py_atomic_ASSERT_ARG_TYPE(unsigned __int8); + __stlr8((unsigned __int8 volatile *)obj, (unsigned __int8)value); +#else +# error "no implementation of _Py_atomic_store_uint32_release" +#endif +} + static inline void _Py_atomic_store_uint32_release(uint32_t *obj, uint32_t value) { diff --git a/Include/cpython/pyatomic_std.h b/Include/cpython/pyatomic_std.h index 7c71e94c68f8e6..74efb440e2768a 100644 --- a/Include/cpython/pyatomic_std.h +++ b/Include/cpython/pyatomic_std.h @@ -911,6 +911,14 @@ _Py_atomic_load_int_acquire(const int *obj) memory_order_acquire); } +static inline void +_Py_atomic_store_uint8_release(uint8_t *obj, uint8_t value) +{ + _Py_USING_STD; + atomic_store_explicit((_Atomic(uint8_t)*)obj, value, + memory_order_release); +} + static inline void _Py_atomic_store_uint32_release(uint32_t *obj, uint32_t value) { diff --git a/Objects/object.c b/Objects/object.c index eb72d58858ecaf..8a9630e3d30add 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -2360,10 +2360,10 @@ new_reference(PyObject *op) #if !defined(Py_GIL_DISABLED) op->ob_refcnt = 1; #else - op->ob_tid = _Py_ThreadId(); + _Py_atomic_store_uintptr_release(&op->ob_tid, _Py_ThreadId()); op->_padding = 0; op->ob_mutex = (PyMutex){ 0 }; - op->ob_gc_bits = 0; + _Py_atomic_store_uint8_release(&op->ob_gc_bits, 0); _Py_atomic_store_uint32_release(&op->ob_ref_local, 1); _Py_atomic_store_ssize_release(&op->ob_ref_shared, 0); #endif From ef99cb93a5800c6b16bcd792bdedcbc5e5a91fa7 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Tue, 23 Jul 2024 00:21:37 +0800 Subject: [PATCH 4/6] Update Include/cpython/pyatomic_msc.h Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> --- Include/cpython/pyatomic_msc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/cpython/pyatomic_msc.h b/Include/cpython/pyatomic_msc.h index 4c52f043fed99d..9fe9320db943da 100644 --- a/Include/cpython/pyatomic_msc.h +++ b/Include/cpython/pyatomic_msc.h @@ -998,7 +998,7 @@ _Py_atomic_store_uint8_release(uint8_t *obj, uint8_t value) _Py_atomic_ASSERT_ARG_TYPE(unsigned __int8); __stlr8((unsigned __int8 volatile *)obj, (unsigned __int8)value); #else -# error "no implementation of _Py_atomic_store_uint32_release" +# error "no implementation of _Py_atomic_store_uint8_release" #endif } From 951a34d6743286eb9ee203d6c763df4c499ef081 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Wed, 24 Jul 2024 21:28:36 +0800 Subject: [PATCH 5/6] revert atomics --- Include/cpython/pyatomic_gcc.h | 4 ---- Include/cpython/pyatomic_msc.h | 13 ------------- Include/cpython/pyatomic_std.h | 8 -------- Objects/object.c | 8 ++++---- 4 files changed, 4 insertions(+), 29 deletions(-) diff --git a/Include/cpython/pyatomic_gcc.h b/Include/cpython/pyatomic_gcc.h index 975bf9f988ae2e..ef09954d53ac1d 100644 --- a/Include/cpython/pyatomic_gcc.h +++ b/Include/cpython/pyatomic_gcc.h @@ -516,10 +516,6 @@ static inline int _Py_atomic_load_int_acquire(const int *obj) { return __atomic_load_n(obj, __ATOMIC_ACQUIRE); } -static inline void -_Py_atomic_store_uint8_release(uint8_t *obj, uint8_t value) -{ __atomic_store_n(obj, value, __ATOMIC_RELEASE); } - static inline void _Py_atomic_store_uint32_release(uint32_t *obj, uint32_t value) { __atomic_store_n(obj, value, __ATOMIC_RELEASE); } diff --git a/Include/cpython/pyatomic_msc.h b/Include/cpython/pyatomic_msc.h index 9fe9320db943da..84da21bdcbff4f 100644 --- a/Include/cpython/pyatomic_msc.h +++ b/Include/cpython/pyatomic_msc.h @@ -989,19 +989,6 @@ _Py_atomic_load_int_acquire(const int *obj) #endif } -static inline void -_Py_atomic_store_uint8_release(uint8_t *obj, uint8_t value) -{ -#if defined(_M_X64) || defined(_M_IX86) - *(uint8_t volatile *)obj = value; -#elif defined(_M_ARM64) - _Py_atomic_ASSERT_ARG_TYPE(unsigned __int8); - __stlr8((unsigned __int8 volatile *)obj, (unsigned __int8)value); -#else -# error "no implementation of _Py_atomic_store_uint8_release" -#endif -} - static inline void _Py_atomic_store_uint32_release(uint32_t *obj, uint32_t value) { diff --git a/Include/cpython/pyatomic_std.h b/Include/cpython/pyatomic_std.h index 74efb440e2768a..7c71e94c68f8e6 100644 --- a/Include/cpython/pyatomic_std.h +++ b/Include/cpython/pyatomic_std.h @@ -911,14 +911,6 @@ _Py_atomic_load_int_acquire(const int *obj) memory_order_acquire); } -static inline void -_Py_atomic_store_uint8_release(uint8_t *obj, uint8_t value) -{ - _Py_USING_STD; - atomic_store_explicit((_Atomic(uint8_t)*)obj, value, - memory_order_release); -} - static inline void _Py_atomic_store_uint32_release(uint32_t *obj, uint32_t value) { diff --git a/Objects/object.c b/Objects/object.c index 8a9630e3d30add..c4622359bb1035 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -2360,12 +2360,12 @@ new_reference(PyObject *op) #if !defined(Py_GIL_DISABLED) op->ob_refcnt = 1; #else - _Py_atomic_store_uintptr_release(&op->ob_tid, _Py_ThreadId()); + op->ob_tid = _Py_ThreadId(); op->_padding = 0; op->ob_mutex = (PyMutex){ 0 }; - _Py_atomic_store_uint8_release(&op->ob_gc_bits, 0); - _Py_atomic_store_uint32_release(&op->ob_ref_local, 1); - _Py_atomic_store_ssize_release(&op->ob_ref_shared, 0); + op->ob_gc_bits = 0; + op->ob_ref_local = 1; + op->ob_ref_shared = 0; #endif #ifdef Py_TRACE_REFS _Py_AddToAllObjects(op); From 6e0e17663260c5e7bec2cd29bfff4fa372411684 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Wed, 24 Jul 2024 22:09:54 +0800 Subject: [PATCH 6/6] Use argumentclinic --- Objects/clinic/exceptions.c.h | 61 +++++++++++++++++++++++++++++++++++ Objects/exceptions.c | 54 ++++++++++++++++--------------- 2 files changed, 89 insertions(+), 26 deletions(-) create mode 100644 Objects/clinic/exceptions.c.h diff --git a/Objects/clinic/exceptions.c.h b/Objects/clinic/exceptions.c.h new file mode 100644 index 00000000000000..fd7d69b20db1dc --- /dev/null +++ b/Objects/clinic/exceptions.c.h @@ -0,0 +1,61 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION() + +#if defined(BaseException___traceback___HAS_DOCSTR) +# define BaseException___traceback___DOCSTR BaseException___traceback____doc__ +#else +# define BaseException___traceback___DOCSTR NULL +#endif +#if defined(BASEEXCEPTION___TRACEBACK___GETSETDEF) +# undef BASEEXCEPTION___TRACEBACK___GETSETDEF +# define BASEEXCEPTION___TRACEBACK___GETSETDEF {"__traceback__", (getter)BaseException___traceback___get, (setter)BaseException___traceback___set, BaseException___traceback___DOCSTR}, +#else +# define BASEEXCEPTION___TRACEBACK___GETSETDEF {"__traceback__", (getter)BaseException___traceback___get, NULL, BaseException___traceback___DOCSTR}, +#endif + +static PyObject * +BaseException___traceback___get_impl(PyBaseExceptionObject *self); + +static PyObject * +BaseException___traceback___get(PyBaseExceptionObject *self, void *Py_UNUSED(context)) +{ + PyObject *return_value = NULL; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = BaseException___traceback___get_impl(self); + Py_END_CRITICAL_SECTION(); + + return return_value; +} + +#if defined(BASEEXCEPTION___TRACEBACK___HAS_DOCSTR) +# define BaseException___traceback___DOCSTR BaseException___traceback____doc__ +#else +# define BaseException___traceback___DOCSTR NULL +#endif +#if defined(BASEEXCEPTION___TRACEBACK___GETSETDEF) +# undef BASEEXCEPTION___TRACEBACK___GETSETDEF +# define BASEEXCEPTION___TRACEBACK___GETSETDEF {"__traceback__", (getter)BaseException___traceback___get, (setter)BaseException___traceback___set, BaseException___traceback___DOCSTR}, +#else +# define BASEEXCEPTION___TRACEBACK___GETSETDEF {"__traceback__", NULL, (setter)BaseException___traceback___set, NULL}, +#endif + +static int +BaseException___traceback___set_impl(PyBaseExceptionObject *self, + PyObject *value); + +static int +BaseException___traceback___set(PyBaseExceptionObject *self, PyObject *value, void *Py_UNUSED(context)) +{ + int return_value; + + Py_BEGIN_CRITICAL_SECTION(self); + return_value = BaseException___traceback___set_impl(self, value); + Py_END_CRITICAL_SECTION(); + + return return_value; +} +/*[clinic end generated code: output=4821907e4f70fde6 input=a9049054013a1b77]*/ diff --git a/Objects/exceptions.c b/Objects/exceptions.c index e0925190993386..c6c49d2fcea013 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -16,6 +16,12 @@ #include "osdefs.h" // SEP +#include "clinic/exceptions.c.h" + +/*[clinic input] +class BaseException "PyBaseExceptionObject *" "&PyExc_BaseException" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=90558eb0fbf8a3d0]*/ /* Compatibility aliases */ PyObject *PyExc_EnvironmentError = NULL; // borrowed ref @@ -307,8 +313,15 @@ BaseException_set_args(PyBaseExceptionObject *self, PyObject *val, void *Py_UNUS return 0; } +/*[clinic input] +@critical_section +@getter +BaseException.__traceback__ +[clinic start generated code]*/ + static PyObject * -BaseException_get_tb_lock_held(PyBaseExceptionObject *self, void *Py_UNUSED(ignored)) +BaseException___traceback___get_impl(PyBaseExceptionObject *self) +/*[clinic end generated code: output=17cf874a52339398 input=a2277f0de62170cf]*/ { if (self->traceback == NULL) { Py_RETURN_NONE; @@ -316,27 +329,25 @@ BaseException_get_tb_lock_held(PyBaseExceptionObject *self, void *Py_UNUSED(igno return Py_NewRef(self->traceback); } -static PyObject * -BaseException_get_tb(PyBaseExceptionObject *self, void *Py_UNUSED(ignored)) -{ - PyObject *res; - Py_BEGIN_CRITICAL_SECTION(self); - res = BaseException_get_tb_lock_held(self, NULL); - Py_END_CRITICAL_SECTION(); - return res; -} +/*[clinic input] +@critical_section +@setter +BaseException.__traceback__ +[clinic start generated code]*/ static int -BaseException_set_tb_lock_held(PyBaseExceptionObject *self, PyObject *tb, void *Py_UNUSED(ignored)) +BaseException___traceback___set_impl(PyBaseExceptionObject *self, + PyObject *value) +/*[clinic end generated code: output=a82c86d9f29f48f0 input=12676035676badad]*/ { - if (tb == NULL) { + if (value == NULL) { PyErr_SetString(PyExc_TypeError, "__traceback__ may not be deleted"); return -1; } - if (PyTraceBack_Check(tb)) { - Py_XSETREF(self->traceback, Py_NewRef(tb)); + if (PyTraceBack_Check(value)) { + Py_XSETREF(self->traceback, Py_NewRef(value)); } - else if (tb == Py_None) { + else if (value == Py_None) { Py_CLEAR(self->traceback); } else { @@ -347,15 +358,6 @@ BaseException_set_tb_lock_held(PyBaseExceptionObject *self, PyObject *tb, void * return 0; } -static int -BaseException_set_tb(PyBaseExceptionObject *self, PyObject *tb, void *Py_UNUSED(ignored)) -{ - int res; - Py_BEGIN_CRITICAL_SECTION(self); - res = BaseException_set_tb_lock_held(self, tb, NULL); - Py_END_CRITICAL_SECTION(); - return res; -} static PyObject * BaseException_get_context(PyObject *self, void *Py_UNUSED(ignored)) @@ -419,7 +421,7 @@ BaseException_set_cause(PyObject *self, PyObject *arg, void *Py_UNUSED(ignored)) static PyGetSetDef BaseException_getset[] = { {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, {"args", (getter)BaseException_get_args, (setter)BaseException_set_args}, - {"__traceback__", (getter)BaseException_get_tb, (setter)BaseException_set_tb}, + BASEEXCEPTION___TRACEBACK___GETSETDEF {"__context__", BaseException_get_context, BaseException_set_context, PyDoc_STR("exception context")}, {"__cause__", BaseException_get_cause, @@ -439,7 +441,7 @@ PyException_GetTraceback(PyObject *self) int PyException_SetTraceback(PyObject *self, PyObject *tb) { - return BaseException_set_tb(_PyBaseExceptionObject_cast(self), tb, NULL); + return BaseException___traceback___set_impl(_PyBaseExceptionObject_cast(self), tb); } PyObject * pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy