@@ -158,11 +158,16 @@ _PyDebug_PrintTotalRefs(void) {
158
158
Do not call them otherwise, they do not initialize the object! */
159
159
160
160
#ifdef Py_TRACE_REFS
161
- /* Head of circular doubly-linked list of all objects. These are linked
162
- * together via the _ob_prev and _ob_next members of a PyObject, which
163
- * exist only in a Py_TRACE_REFS build.
164
- */
165
- static PyObject refchain = {& refchain , & refchain };
161
+
162
+ #define REFCHAIN (interp ) &interp->object_state.refchain
163
+
164
+ static inline void
165
+ init_refchain (PyInterpreterState * interp )
166
+ {
167
+ PyObject * refchain = REFCHAIN (interp );
168
+ refchain -> _ob_prev = refchain ;
169
+ refchain -> _ob_next = refchain ;
170
+ }
166
171
167
172
/* Insert op at the front of the list of all objects. If force is true,
168
173
* op is added even if _ob_prev and _ob_next are non-NULL already. If
@@ -187,10 +192,11 @@ _Py_AddToAllObjects(PyObject *op, int force)
187
192
}
188
193
#endif
189
194
if (force || op -> _ob_prev == NULL ) {
190
- op -> _ob_next = refchain ._ob_next ;
191
- op -> _ob_prev = & refchain ;
192
- refchain ._ob_next -> _ob_prev = op ;
193
- refchain ._ob_next = op ;
195
+ PyObject * refchain = REFCHAIN (_PyInterpreterState_GET ());
196
+ op -> _ob_next = refchain -> _ob_next ;
197
+ op -> _ob_prev = refchain ;
198
+ refchain -> _ob_next -> _ob_prev = op ;
199
+ refchain -> _ob_next = op ;
194
200
}
195
201
}
196
202
#endif /* Py_TRACE_REFS */
@@ -1998,6 +2004,18 @@ PyObject _Py_NotImplementedStruct = {
1998
2004
& _PyNotImplemented_Type
1999
2005
};
2000
2006
2007
+
2008
+ void
2009
+ _PyObject_InitState (PyInterpreterState * interp )
2010
+ {
2011
+ #ifdef Py_TRACE_REFS
2012
+ if (!_Py_IsMainInterpreter (interp )) {
2013
+ init_refchain (interp );
2014
+ }
2015
+ #endif
2016
+ }
2017
+
2018
+
2001
2019
extern PyTypeObject _Py_GenericAliasIterType ;
2002
2020
extern PyTypeObject _PyMemoryIter_Type ;
2003
2021
extern PyTypeObject _PyLineIterator ;
@@ -2206,20 +2224,21 @@ _Py_ForgetReference(PyObject *op)
2206
2224
_PyObject_ASSERT_FAILED_MSG (op , "negative refcnt" );
2207
2225
}
2208
2226
2209
- if (op == & refchain ||
2227
+ PyObject * refchain = REFCHAIN (_PyInterpreterState_GET ());
2228
+ if (op == refchain ||
2210
2229
op -> _ob_prev -> _ob_next != op || op -> _ob_next -> _ob_prev != op )
2211
2230
{
2212
2231
_PyObject_ASSERT_FAILED_MSG (op , "invalid object chain" );
2213
2232
}
2214
2233
2215
2234
#ifdef SLOW_UNREF_CHECK
2216
2235
PyObject * p ;
2217
- for (p = refchain . _ob_next ; p != & refchain ; p = p -> _ob_next ) {
2236
+ for (p = refchain -> _ob_next ; p != refchain ; p = p -> _ob_next ) {
2218
2237
if (p == op ) {
2219
2238
break ;
2220
2239
}
2221
2240
}
2222
- if (p == & refchain ) {
2241
+ if (p == refchain ) {
2223
2242
/* Not found */
2224
2243
_PyObject_ASSERT_FAILED_MSG (op ,
2225
2244
"object not found in the objects list" );
@@ -2235,11 +2254,15 @@ _Py_ForgetReference(PyObject *op)
2235
2254
* interpreter must be in a healthy state.
2236
2255
*/
2237
2256
void
2238
- _Py_PrintReferences (FILE * fp )
2257
+ _Py_PrintReferences (PyInterpreterState * interp , FILE * fp )
2239
2258
{
2240
2259
PyObject * op ;
2260
+ if (interp == NULL ) {
2261
+ interp = _PyInterpreterState_Main ();
2262
+ }
2241
2263
fprintf (fp , "Remaining objects:\n" );
2242
- for (op = refchain ._ob_next ; op != & refchain ; op = op -> _ob_next ) {
2264
+ PyObject * refchain = REFCHAIN (interp );
2265
+ for (op = refchain -> _ob_next ; op != refchain ; op = op -> _ob_next ) {
2243
2266
fprintf (fp , "%p [%zd] " , (void * )op , Py_REFCNT (op ));
2244
2267
if (PyObject_Print (op , fp , 0 ) != 0 ) {
2245
2268
PyErr_Clear ();
@@ -2251,34 +2274,42 @@ _Py_PrintReferences(FILE *fp)
2251
2274
/* Print the addresses of all live objects. Unlike _Py_PrintReferences, this
2252
2275
* doesn't make any calls to the Python C API, so is always safe to call.
2253
2276
*/
2277
+ // XXX This function is not safe to use if the interpreter has been
2278
+ // freed or is in an unhealthy state (e.g. late in finalization).
2279
+ // The call in Py_FinalizeEx() is okay since the main interpreter
2280
+ // is statically allocated.
2254
2281
void
2255
- _Py_PrintReferenceAddresses (FILE * fp )
2282
+ _Py_PrintReferenceAddresses (PyInterpreterState * interp , FILE * fp )
2256
2283
{
2257
2284
PyObject * op ;
2285
+ PyObject * refchain = REFCHAIN (interp );
2258
2286
fprintf (fp , "Remaining object addresses:\n" );
2259
- for (op = refchain . _ob_next ; op != & refchain ; op = op -> _ob_next )
2287
+ for (op = refchain -> _ob_next ; op != refchain ; op = op -> _ob_next )
2260
2288
fprintf (fp , "%p [%zd] %s\n" , (void * )op ,
2261
2289
Py_REFCNT (op ), Py_TYPE (op )-> tp_name );
2262
2290
}
2263
2291
2292
+ /* The implementation of sys.getobjects(). */
2264
2293
PyObject *
2265
2294
_Py_GetObjects (PyObject * self , PyObject * args )
2266
2295
{
2267
2296
int i , n ;
2268
2297
PyObject * t = NULL ;
2269
2298
PyObject * res , * op ;
2299
+ PyInterpreterState * interp = _PyInterpreterState_GET ();
2270
2300
2271
2301
if (!PyArg_ParseTuple (args , "i|O" , & n , & t ))
2272
2302
return NULL ;
2273
- op = refchain ._ob_next ;
2303
+ PyObject * refchain = REFCHAIN (interp );
2304
+ op = refchain -> _ob_next ;
2274
2305
res = PyList_New (0 );
2275
2306
if (res == NULL )
2276
2307
return NULL ;
2277
- for (i = 0 ; (n == 0 || i < n ) && op != & refchain ; i ++ ) {
2308
+ for (i = 0 ; (n == 0 || i < n ) && op != refchain ; i ++ ) {
2278
2309
while (op == self || op == args || op == res || op == t ||
2279
2310
(t != NULL && !Py_IS_TYPE (op , (PyTypeObject * ) t ))) {
2280
2311
op = op -> _ob_next ;
2281
- if (op == & refchain )
2312
+ if (op == refchain )
2282
2313
return res ;
2283
2314
}
2284
2315
if (PyList_Append (res , op ) < 0 ) {
@@ -2290,7 +2321,9 @@ _Py_GetObjects(PyObject *self, PyObject *args)
2290
2321
return res ;
2291
2322
}
2292
2323
2293
- #endif
2324
+ #undef REFCHAIN
2325
+
2326
+ #endif /* Py_TRACE_REFS */
2294
2327
2295
2328
2296
2329
/* Hack to force loading of abstract.o */
0 commit comments