@@ -159,11 +159,8 @@ _PyDebug_PrintTotalRefs(void) {
159
159
Do not call them otherwise, they do not initialize the object! */
160
160
161
161
#ifdef Py_TRACE_REFS
162
- /* Head of circular doubly-linked list of all objects. These are linked
163
- * together via the _ob_prev and _ob_next members of a PyObject, which
164
- * exist only in a Py_TRACE_REFS build.
165
- */
166
- static PyObject refchain = {& refchain , & refchain };
162
+
163
+ #define REFCHAIN (interp ) &interp->object_state.refchain
167
164
168
165
/* Insert op at the front of the list of all objects. If force is true,
169
166
* op is added even if _ob_prev and _ob_next are non-NULL already. If
@@ -188,10 +185,11 @@ _Py_AddToAllObjects(PyObject *op, int force)
188
185
}
189
186
#endif
190
187
if (force || op -> _ob_prev == NULL ) {
191
- op -> _ob_next = refchain ._ob_next ;
192
- op -> _ob_prev = & refchain ;
193
- refchain ._ob_next -> _ob_prev = op ;
194
- refchain ._ob_next = op ;
188
+ PyObject * refchain = REFCHAIN (_PyInterpreterState_GET ());
189
+ op -> _ob_next = refchain -> _ob_next ;
190
+ op -> _ob_prev = refchain ;
191
+ refchain -> _ob_next -> _ob_prev = op ;
192
+ refchain -> _ob_next = op ;
195
193
}
196
194
}
197
195
#endif /* Py_TRACE_REFS */
@@ -2229,20 +2227,21 @@ _Py_ForgetReference(PyObject *op)
2229
2227
_PyObject_ASSERT_FAILED_MSG (op , "negative refcnt" );
2230
2228
}
2231
2229
2232
- if (op == & refchain ||
2230
+ PyObject * refchain = REFCHAIN (_PyInterpreterState_GET ());
2231
+ if (op == refchain ||
2233
2232
op -> _ob_prev -> _ob_next != op || op -> _ob_next -> _ob_prev != op )
2234
2233
{
2235
2234
_PyObject_ASSERT_FAILED_MSG (op , "invalid object chain" );
2236
2235
}
2237
2236
2238
2237
#ifdef SLOW_UNREF_CHECK
2239
2238
PyObject * p ;
2240
- for (p = refchain . _ob_next ; p != & refchain ; p = p -> _ob_next ) {
2239
+ for (p = refchain -> _ob_next ; p != refchain ; p = p -> _ob_next ) {
2241
2240
if (p == op ) {
2242
2241
break ;
2243
2242
}
2244
2243
}
2245
- if (p == & refchain ) {
2244
+ if (p == refchain ) {
2246
2245
/* Not found */
2247
2246
_PyObject_ASSERT_FAILED_MSG (op ,
2248
2247
"object not found in the objects list" );
@@ -2258,11 +2257,15 @@ _Py_ForgetReference(PyObject *op)
2258
2257
* interpreter must be in a healthy state.
2259
2258
*/
2260
2259
void
2261
- _Py_PrintReferences (FILE * fp )
2260
+ _Py_PrintReferences (PyInterpreterState * interp , FILE * fp )
2262
2261
{
2263
2262
PyObject * op ;
2263
+ if (interp == NULL ) {
2264
+ interp = _PyInterpreterState_Main ();
2265
+ }
2264
2266
fprintf (fp , "Remaining objects:\n" );
2265
- for (op = refchain ._ob_next ; op != & refchain ; op = op -> _ob_next ) {
2267
+ PyObject * refchain = REFCHAIN (interp );
2268
+ for (op = refchain -> _ob_next ; op != refchain ; op = op -> _ob_next ) {
2266
2269
fprintf (fp , "%p [%zd] " , (void * )op , Py_REFCNT (op ));
2267
2270
if (PyObject_Print (op , fp , 0 ) != 0 ) {
2268
2271
PyErr_Clear ();
@@ -2274,34 +2277,42 @@ _Py_PrintReferences(FILE *fp)
2274
2277
/* Print the addresses of all live objects. Unlike _Py_PrintReferences, this
2275
2278
* doesn't make any calls to the Python C API, so is always safe to call.
2276
2279
*/
2280
+ // XXX This function is not safe to use if the interpreter has been
2281
+ // freed or is in an unhealthy state (e.g. late in finalization).
2282
+ // The call in Py_FinalizeEx() is okay since the main interpreter
2283
+ // is statically allocated.
2277
2284
void
2278
- _Py_PrintReferenceAddresses (FILE * fp )
2285
+ _Py_PrintReferenceAddresses (PyInterpreterState * interp , FILE * fp )
2279
2286
{
2280
2287
PyObject * op ;
2288
+ PyObject * refchain = REFCHAIN (interp );
2281
2289
fprintf (fp , "Remaining object addresses:\n" );
2282
- for (op = refchain . _ob_next ; op != & refchain ; op = op -> _ob_next )
2290
+ for (op = refchain -> _ob_next ; op != refchain ; op = op -> _ob_next )
2283
2291
fprintf (fp , "%p [%zd] %s\n" , (void * )op ,
2284
2292
Py_REFCNT (op ), Py_TYPE (op )-> tp_name );
2285
2293
}
2286
2294
2295
+ /* The implementation of sys.getobjects(). */
2287
2296
PyObject *
2288
2297
_Py_GetObjects (PyObject * self , PyObject * args )
2289
2298
{
2290
2299
int i , n ;
2291
2300
PyObject * t = NULL ;
2292
2301
PyObject * res , * op ;
2302
+ PyInterpreterState * interp = _PyInterpreterState_GET ();
2293
2303
2294
2304
if (!PyArg_ParseTuple (args , "i|O" , & n , & t ))
2295
2305
return NULL ;
2296
- op = refchain ._ob_next ;
2306
+ PyObject * refchain = REFCHAIN (interp );
2307
+ op = refchain -> _ob_next ;
2297
2308
res = PyList_New (0 );
2298
2309
if (res == NULL )
2299
2310
return NULL ;
2300
- for (i = 0 ; (n == 0 || i < n ) && op != & refchain ; i ++ ) {
2311
+ for (i = 0 ; (n == 0 || i < n ) && op != refchain ; i ++ ) {
2301
2312
while (op == self || op == args || op == res || op == t ||
2302
2313
(t != NULL && !Py_IS_TYPE (op , (PyTypeObject * ) t ))) {
2303
2314
op = op -> _ob_next ;
2304
- if (op == & refchain )
2315
+ if (op == refchain )
2305
2316
return res ;
2306
2317
}
2307
2318
if (PyList_Append (res , op ) < 0 ) {
@@ -2313,6 +2324,8 @@ _Py_GetObjects(PyObject *self, PyObject *args)
2313
2324
return res ;
2314
2325
}
2315
2326
2327
+ #undef REFCHAIN
2328
+
2316
2329
#endif
2317
2330
2318
2331
0 commit comments