diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 5a9403456903ed..0981d1122fec54 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -271,8 +271,8 @@ extern void _PyDebug_PrintTotalRefs(void); #ifdef Py_TRACE_REFS extern void _Py_AddToAllObjects(PyObject *op, int force); -extern void _Py_PrintReferences(PyInterpreterState *, FILE *); -extern void _Py_PrintReferenceAddresses(PyInterpreterState *, FILE *); +extern void _Py_PrintReferences(FILE *); +extern void _Py_PrintReferenceAddresses(FILE *); #endif diff --git a/Include/internal/pycore_object_state.h b/Include/internal/pycore_object_state.h index 65feb5af969f8b..94005d77881432 100644 --- a/Include/internal/pycore_object_state.h +++ b/Include/internal/pycore_object_state.h @@ -11,22 +11,17 @@ extern "C" { struct _py_object_runtime_state { #ifdef Py_REF_DEBUG Py_ssize_t interpreter_leaks; -#endif +#else int _not_used; +#endif }; struct _py_object_state { #ifdef Py_REF_DEBUG Py_ssize_t reftotal; -#endif -#ifdef Py_TRACE_REFS - /* Head of circular doubly-linked list of all objects. These are linked - * together via the _ob_prev and _ob_next members of a PyObject, which - * exist only in a Py_TRACE_REFS build. - */ - PyObject refchain; -#endif +#else int _not_used; +#endif }; diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index 7aace9f86119c4..4130188079cffa 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -101,7 +101,6 @@ extern PyTypeObject _PyExc_MemoryError; { .threshold = 10, }, \ }, \ }, \ - .object_state = _py_object_state_INIT(INTERP), \ .dtoa = _dtoa_state_INIT(&(INTERP)), \ .dict_state = _dict_state_INIT, \ .func_state = { \ @@ -131,16 +130,6 @@ extern PyTypeObject _PyExc_MemoryError; .context_ver = 1, \ } -#ifdef Py_TRACE_REFS -# define _py_object_state_INIT(INTERP) \ - { \ - .refchain = {&INTERP.object_state.refchain, &INTERP.object_state.refchain}, \ - } -#else -# define _py_object_state_INIT(INTERP) \ - { 0 } -#endif - // global objects diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-08-02-12-24-51.gh-issue-107080.PNolFU.rst b/Misc/NEWS.d/next/Core and Builtins/2023-08-02-12-24-51.gh-issue-107080.PNolFU.rst deleted file mode 100644 index 5084c854360e35..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2023-08-02-12-24-51.gh-issue-107080.PNolFU.rst +++ /dev/null @@ -1,4 +0,0 @@ -Trace refs builds (``--with-trace-refs``) were crashing when used with -isolated subinterpreters. The problematic global state has been isolated to -each interpreter. Other fixing the crashes, this change does not affect -users. diff --git a/Objects/object.c b/Objects/object.c index b4c9416036c44e..bd0fa40bd2a851 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -158,8 +158,11 @@ _PyDebug_PrintTotalRefs(void) { Do not call them otherwise, they do not initialize the object! */ #ifdef Py_TRACE_REFS - -#define REFCHAIN(interp) &interp->object_state.refchain +/* Head of circular doubly-linked list of all objects. These are linked + * together via the _ob_prev and _ob_next members of a PyObject, which + * exist only in a Py_TRACE_REFS build. + */ +static PyObject refchain = {&refchain, &refchain}; /* Insert op at the front of the list of all objects. If force is true, * op is added even if _ob_prev and _ob_next are non-NULL already. If @@ -184,11 +187,10 @@ _Py_AddToAllObjects(PyObject *op, int force) } #endif if (force || op->_ob_prev == NULL) { - PyObject *refchain = REFCHAIN(_PyInterpreterState_GET()); - op->_ob_next = refchain->_ob_next; - op->_ob_prev = refchain; - refchain->_ob_next->_ob_prev = op; - refchain->_ob_next = op; + op->_ob_next = refchain._ob_next; + op->_ob_prev = &refchain; + refchain._ob_next->_ob_prev = op; + refchain._ob_next = op; } } #endif /* Py_TRACE_REFS */ @@ -2204,8 +2206,7 @@ _Py_ForgetReference(PyObject *op) _PyObject_ASSERT_FAILED_MSG(op, "negative refcnt"); } - PyObject *refchain = REFCHAIN(_PyInterpreterState_GET()); - if (op == refchain || + if (op == &refchain || op->_ob_prev->_ob_next != op || op->_ob_next->_ob_prev != op) { _PyObject_ASSERT_FAILED_MSG(op, "invalid object chain"); @@ -2213,12 +2214,12 @@ _Py_ForgetReference(PyObject *op) #ifdef SLOW_UNREF_CHECK PyObject *p; - for (p = refchain->_ob_next; p != refchain; p = p->_ob_next) { + for (p = refchain._ob_next; p != &refchain; p = p->_ob_next) { if (p == op) { break; } } - if (p == refchain) { + if (p == &refchain) { /* Not found */ _PyObject_ASSERT_FAILED_MSG(op, "object not found in the objects list"); @@ -2234,15 +2235,11 @@ _Py_ForgetReference(PyObject *op) * interpreter must be in a healthy state. */ void -_Py_PrintReferences(PyInterpreterState *interp, FILE *fp) +_Py_PrintReferences(FILE *fp) { PyObject *op; - if (interp == NULL) { - interp = _PyInterpreterState_Main(); - } fprintf(fp, "Remaining objects:\n"); - PyObject *refchain = REFCHAIN(interp); - for (op = refchain->_ob_next; op != refchain; op = op->_ob_next) { + for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) { fprintf(fp, "%p [%zd] ", (void *)op, Py_REFCNT(op)); if (PyObject_Print(op, fp, 0) != 0) { PyErr_Clear(); @@ -2254,42 +2251,34 @@ _Py_PrintReferences(PyInterpreterState *interp, FILE *fp) /* Print the addresses of all live objects. Unlike _Py_PrintReferences, this * doesn't make any calls to the Python C API, so is always safe to call. */ -// XXX This function is not safe to use if the interpreter has been -// freed or is in an unhealthy state (e.g. late in finalization). -// The call in Py_FinalizeEx() is okay since the main interpreter -// is statically allocated. void -_Py_PrintReferenceAddresses(PyInterpreterState *interp, FILE *fp) +_Py_PrintReferenceAddresses(FILE *fp) { PyObject *op; - PyObject *refchain = REFCHAIN(interp); fprintf(fp, "Remaining object addresses:\n"); - for (op = refchain->_ob_next; op != refchain; op = op->_ob_next) + for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) fprintf(fp, "%p [%zd] %s\n", (void *)op, Py_REFCNT(op), Py_TYPE(op)->tp_name); } -/* The implementation of sys.getobjects(). */ PyObject * _Py_GetObjects(PyObject *self, PyObject *args) { int i, n; PyObject *t = NULL; PyObject *res, *op; - PyInterpreterState *interp = _PyInterpreterState_GET(); if (!PyArg_ParseTuple(args, "i|O", &n, &t)) return NULL; - PyObject *refchain = REFCHAIN(interp); - op = refchain->_ob_next; + op = refchain._ob_next; res = PyList_New(0); if (res == NULL) return NULL; - for (i = 0; (n == 0 || i < n) && op != refchain; i++) { + for (i = 0; (n == 0 || i < n) && op != &refchain; i++) { while (op == self || op == args || op == res || op == t || (t != NULL && !Py_IS_TYPE(op, (PyTypeObject *) t))) { op = op->_ob_next; - if (op == refchain) + if (op == &refchain) return res; } if (PyList_Append(res, op) < 0) { @@ -2301,8 +2290,6 @@ _Py_GetObjects(PyObject *self, PyObject *args) return res; } -#undef REFCHAIN - #endif diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 5b8c8af179c005..a67fa26b372278 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1920,11 +1920,11 @@ Py_FinalizeEx(void) } if (dump_refs) { - _Py_PrintReferences(tstate->interp, stderr); + _Py_PrintReferences(stderr); } if (dump_refs_fp != NULL) { - _Py_PrintReferences(tstate->interp, dump_refs_fp); + _Py_PrintReferences(dump_refs_fp); } #endif /* Py_TRACE_REFS */ @@ -1960,11 +1960,11 @@ Py_FinalizeEx(void) */ if (dump_refs) { - _Py_PrintReferenceAddresses(tstate->interp, stderr); + _Py_PrintReferenceAddresses(stderr); } if (dump_refs_fp != NULL) { - _Py_PrintReferenceAddresses(tstate->interp, dump_refs_fp); + _Py_PrintReferenceAddresses(dump_refs_fp); fclose(dump_refs_fp); } #endif /* Py_TRACE_REFS */
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: