From 6632a253d4dc9793729df55b3ae7a901d2d74c8a Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 14 May 2026 15:55:53 +0300 Subject: [PATCH 1/2] gh-149816: Fix a RC in `_random.Random.__init__` method --- ...-05-14-15-55-28.gh-issue-149816.ZaXQ0q.rst | 2 ++ Modules/_randommodule.c | 33 ++++++++----------- Modules/clinic/_randommodule.c.h | 33 ++++++++++++++++++- 3 files changed, 47 insertions(+), 21 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-05-14-15-55-28.gh-issue-149816.ZaXQ0q.rst diff --git a/Misc/NEWS.d/next/Library/2026-05-14-15-55-28.gh-issue-149816.ZaXQ0q.rst b/Misc/NEWS.d/next/Library/2026-05-14-15-55-28.gh-issue-149816.ZaXQ0q.rst new file mode 100644 index 00000000000000..3ea70071ec3c75 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-14-15-55-28.gh-issue-149816.ZaXQ0q.rst @@ -0,0 +1,2 @@ +Fix a race condition in ``_random.Random.__init__`` method in free-threading +mode. diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c index 0fb73481651748..29874b9bb0add9 100644 --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -123,9 +123,9 @@ typedef struct { /*[clinic input] module _random -class _random.Random "RandomObject *" "_randomstate_type(type)->Random_Type" +class _random.Random "RandomObject *" "(PyTypeObject *)_randomstate_type(Py_TYPE(self))->Random_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=70a2c99619474983]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f04bcbfba61a322e]*/ /* Random methods */ @@ -549,26 +549,19 @@ _random_Random_getrandbits_impl(RandomObject *self, uint64_t k) return result; } -static int -random_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *arg = NULL; - _randomstate *state = _randomstate_type(Py_TYPE(self)); - - if ((Py_IS_TYPE(self, (PyTypeObject *)state->Random_Type) || - Py_TYPE(self)->tp_init == ((PyTypeObject*)state->Random_Type)->tp_init) && - !_PyArg_NoKeywords("Random", kwds)) { - return -1; - } - - if (PyTuple_GET_SIZE(args) > 1) { - PyErr_SetString(PyExc_TypeError, "Random() requires 0 or 1 argument"); - return -1; - } +/*[clinic input] +@critical_section +@text_signature "($self, /, *args, **kwargs)" +_random.Random.__init__ as random_init - if (PyTuple_GET_SIZE(args) == 1) - arg = PyTuple_GET_ITEM(args, 0); + arg: object = NULL + / +[clinic start generated code]*/ +static int +random_init_impl(RandomObject *self, PyObject *arg) +/*[clinic end generated code: output=823329df8669c8a7 input=3772473c67871d42]*/ +{ return random_seed(RandomObject_CAST(self), arg); } diff --git a/Modules/clinic/_randommodule.c.h b/Modules/clinic/_randommodule.c.h index 2563a16aea0b6f..cdb989d1d8e6ab 100644 --- a/Modules/clinic/_randommodule.c.h +++ b/Modules/clinic/_randommodule.c.h @@ -143,4 +143,35 @@ _random_Random_getrandbits(PyObject *self, PyObject *arg) exit: return return_value; } -/*[clinic end generated code: output=7ce97b2194eecaf7 input=a9049054013a1b77]*/ + +static int +random_init_impl(RandomObject *self, PyObject *arg); + +static int +random_init(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + PyTypeObject *base_tp = (PyTypeObject *)_randomstate_type(Py_TYPE(self))->Random_Type; + PyObject *arg = NULL; + + if ((Py_IS_TYPE(self, base_tp) || + Py_TYPE(self)->tp_new == base_tp->tp_new) && + !_PyArg_NoKeywords("Random", kwargs)) { + goto exit; + } + if (!_PyArg_CheckPositional("Random", PyTuple_GET_SIZE(args), 0, 1)) { + goto exit; + } + if (PyTuple_GET_SIZE(args) < 1) { + goto skip_optional; + } + arg = PyTuple_GET_ITEM(args, 0); +skip_optional: + Py_BEGIN_CRITICAL_SECTION(self); + return_value = random_init_impl((RandomObject *)self, arg); + Py_END_CRITICAL_SECTION(); + +exit: + return return_value; +} +/*[clinic end generated code: output=5d4c7afe866d5104 input=a9049054013a1b77]*/ From de0b35d830b0c9cfc99a330ee9964ff5a1b85384 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Fri, 15 May 2026 13:48:19 +0300 Subject: [PATCH 2/2] Address review --- Modules/_randommodule.c | 10 +++++----- Modules/clinic/_randommodule.c.h | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c index 29874b9bb0add9..a06966be23be1e 100644 --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -551,18 +551,18 @@ _random_Random_getrandbits_impl(RandomObject *self, uint64_t k) /*[clinic input] @critical_section -@text_signature "($self, /, *args, **kwargs)" +@text_signature "($self, [seed])" _random.Random.__init__ as random_init - arg: object = NULL + seed: object = NULL / [clinic start generated code]*/ static int -random_init_impl(RandomObject *self, PyObject *arg) -/*[clinic end generated code: output=823329df8669c8a7 input=3772473c67871d42]*/ +random_init_impl(RandomObject *self, PyObject *seed) +/*[clinic end generated code: output=260734a3739c394f input=e516bf32e8a05e28]*/ { - return random_seed(RandomObject_CAST(self), arg); + return random_seed(self, seed); } diff --git a/Modules/clinic/_randommodule.c.h b/Modules/clinic/_randommodule.c.h index cdb989d1d8e6ab..ca9cad7a572dad 100644 --- a/Modules/clinic/_randommodule.c.h +++ b/Modules/clinic/_randommodule.c.h @@ -145,14 +145,14 @@ _random_Random_getrandbits(PyObject *self, PyObject *arg) } static int -random_init_impl(RandomObject *self, PyObject *arg); +random_init_impl(RandomObject *self, PyObject *seed); static int random_init(PyObject *self, PyObject *args, PyObject *kwargs) { int return_value = -1; PyTypeObject *base_tp = (PyTypeObject *)_randomstate_type(Py_TYPE(self))->Random_Type; - PyObject *arg = NULL; + PyObject *seed = NULL; if ((Py_IS_TYPE(self, base_tp) || Py_TYPE(self)->tp_new == base_tp->tp_new) && @@ -165,13 +165,13 @@ random_init(PyObject *self, PyObject *args, PyObject *kwargs) if (PyTuple_GET_SIZE(args) < 1) { goto skip_optional; } - arg = PyTuple_GET_ITEM(args, 0); + seed = PyTuple_GET_ITEM(args, 0); skip_optional: Py_BEGIN_CRITICAL_SECTION(self); - return_value = random_init_impl((RandomObject *)self, arg); + return_value = random_init_impl((RandomObject *)self, seed); Py_END_CRITICAL_SECTION(); exit: return return_value; } -/*[clinic end generated code: output=5d4c7afe866d5104 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ec95f7df0c3f3c19 input=a9049054013a1b77]*/