[3.15] gh-155363: Fix QSBR slot leak on thread state creation failure (gh-155365) (#155579)
hugovk <[email protected]>
| Newsgroups | gmane.comp.python.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://github.com/python/cpython/commit/dd4bd4c293694c34b098aecb4f19b02961528909 commit: dd4bd4c293694c34b098aecb4f19b02961528909 branch: 3.15 author: Miss Islington (bot) <[email protected]> committer: hugovk <[email protected]> date: 2026-08-22T12:39:14+03:00 summary: [3.15] gh-155363: Fix QSBR slot leak on thread state creation failure (gh-155365) (#155579) Co-authored-by: Neil Schemenauer <[email protected]> Co-authored-by: Kumar Aditya <[email protected]> files: A Misc/NEWS.d/next/Core_and_Builtins/2026-08-07-13-40-12.gh-issue-155363.Qk3Vt9.rst M Include/internal/pycore_code.h M Objects/codeobject.c M Python/pystate.c diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 5b1fddbe15b98b8..32242f89b812e69 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -582,6 +582,10 @@ PyAPI_FUNC(_Py_CODEUNIT *) _PyCode_GetTLBC(PyCodeObject *co); // Returns the reserved index or -1 on error. extern int32_t _Py_ReserveTLBCIndex(PyInterpreterState *interp); +// Release an index returned by _Py_ReserveTLBCIndex() that was never stored +// in a PyThreadState. +extern void _Py_UnreserveTLBCIndex(PyInterpreterState *interp, int32_t index); + // Release the current thread's index into thread-local bytecode arrays extern void _Py_ClearTLBCIndex(_PyThreadStateImpl *tstate); diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-08-07-13-40-12.gh-issue-155363.Qk3Vt9.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-07-13-40-12.gh-issue-155363.Qk3Vt9.rst new file mode 100644 index 000000000000000..52200bb9d2fd59f --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-07-13-40-12.gh-issue-155363.Qk3Vt9.rst @@ -0,0 +1,4 @@ +Fix a leak in the :term:`free-threaded build` when creating a thread state +fails after an internal QSBR slot has been reserved for it. The slot could +never be reclaimed, so the QSBR array grew without bound across repeated +failures. diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 03036020b1cb1ae..d4c96b36e3c8b5b 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -3313,14 +3313,20 @@ _Py_ReserveTLBCIndex(PyInterpreterState *interp) } void -_Py_ClearTLBCIndex(_PyThreadStateImpl *tstate) +_Py_UnreserveTLBCIndex(PyInterpreterState *interp, int32_t index) { - PyInterpreterState *interp = ((PyThreadState *)tstate)->interp; if (interp->config.tlbc_enabled) { - _PyIndexPool_FreeIndex(&interp->tlbc_indices, tstate->tlbc_index); + _PyIndexPool_FreeIndex(&interp->tlbc_indices, index); } } +void +_Py_ClearTLBCIndex(_PyThreadStateImpl *tstate) +{ + PyInterpreterState *interp = ((PyThreadState *)tstate)->interp; + _Py_UnreserveTLBCIndex(interp, tstate->tlbc_index); +} + static _PyCodeArray * _PyCodeArray_New(Py_ssize_t size) { diff --git a/Python/pystate.c b/Python/pystate.c index 8349df1b573952d..d79006639ab4529 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1638,21 +1638,23 @@ new_threadstate(PyInterpreterState *interp, int whence) return NULL; } -#ifdef Py_GIL_DISABLED - Py_ssize_t qsbr_idx = _Py_qsbr_reserve(interp); - if (qsbr_idx < 0) { +#ifdef Py_STATS + // The PyStats structure is quite large and is allocated separated from + // tstate. + if (!_PyStats_ThreadInit(interp, tstate)) { free_threadstate(tstate); return NULL; } +#endif +#ifdef Py_GIL_DISABLED int32_t tlbc_idx = _Py_ReserveTLBCIndex(interp); if (tlbc_idx < 0) { free_threadstate(tstate); return NULL; } -#endif -#ifdef Py_STATS - // The PyStats structure is quite large and is allocated separated from tstate. - if (!_PyStats_ThreadInit(interp, tstate)) { + Py_ssize_t qsbr_idx = _Py_qsbr_reserve(interp); + if (qsbr_idx < 0) { + _Py_UnreserveTLBCIndex(interp, tlbc_idx); free_threadstate(tstate); return NULL; } _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]