Skip to content

Commit 36c5e3b

Browse files
authored
gh-128679: Redesign tracemalloc locking (#128888)
* Use TABLES_LOCK() to protect 'tracemalloc_config.tracing'. * Hold TABLES_LOCK() longer while accessing tables. * tracemalloc_realloc() and tracemalloc_free() no longer remove the trace on reentrant call. * _PyTraceMalloc_Stop() unregisters _PyTraceMalloc_TraceRef(). * _PyTraceMalloc_GetTraces() sets the reentrant flag. * tracemalloc_clear_traces_unlocked() sets the reentrant flag.
1 parent 080f444 commit 36c5e3b

File tree

5 files changed

+294
-356
lines changed

5 files changed

+294
-356
lines changed

Include/internal/pycore_object.h

-6
Original file line numberDiff line numberDiff line change
@@ -299,12 +299,6 @@ Py_ssize_t _Py_ExplicitMergeRefcount(PyObject *op, Py_ssize_t extra);
299299
extern int _PyType_CheckConsistency(PyTypeObject *type);
300300
extern int _PyDict_CheckConsistency(PyObject *mp, int check_content);
301301

302-
/* Update the Python traceback of an object. This function must be called
303-
when a memory block is reused from a free list.
304-
305-
Internal function called by _Py_NewReference(). */
306-
extern int _PyTraceMalloc_TraceRef(PyObject *op, PyRefTracerEvent event, void*);
307-
308302
// Fast inlined version of PyType_HasFeature()
309303
static inline int
310304
_PyType_HasFeature(PyTypeObject *type, unsigned long feature) {

Include/internal/pycore_tracemalloc.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct _PyTraceMalloc_Config {
2525
} initialized;
2626

2727
/* Is tracemalloc tracing memory allocations?
28-
Variable protected by the GIL */
28+
Variable protected by the TABLES_LOCK(). */
2929
int tracing;
3030

3131
/* limit of the number of frames in a traceback, 1 by default.
@@ -85,14 +85,14 @@ struct _tracemalloc_runtime_state {
8585
size_t peak_traced_memory;
8686
/* Hash table used as a set to intern filenames:
8787
PyObject* => PyObject*.
88-
Protected by the GIL */
88+
Protected by the TABLES_LOCK(). */
8989
_Py_hashtable_t *filenames;
9090
/* Buffer to store a new traceback in traceback_new().
91-
Protected by the GIL. */
91+
Protected by the TABLES_LOCK(). */
9292
struct tracemalloc_traceback *traceback;
9393
/* Hash table used as a set to intern tracebacks:
9494
traceback_t* => traceback_t*
95-
Protected by the GIL */
95+
Protected by the TABLES_LOCK(). */
9696
_Py_hashtable_t *tracebacks;
9797
/* pointer (void*) => trace (trace_t*).
9898
Protected by TABLES_LOCK(). */
@@ -144,7 +144,7 @@ extern PyObject* _PyTraceMalloc_GetTraces(void);
144144
extern PyObject* _PyTraceMalloc_GetObjectTraceback(PyObject *obj);
145145

146146
/* Initialize tracemalloc */
147-
extern int _PyTraceMalloc_Init(void);
147+
extern PyStatus _PyTraceMalloc_Init(void);
148148

149149
/* Start tracemalloc */
150150
extern int _PyTraceMalloc_Start(int max_nframe);

Modules/_tracemalloc.c

+6-10
Original file line numberDiff line numberDiff line change
@@ -215,18 +215,14 @@ static struct PyModuleDef module_def = {
215215
PyMODINIT_FUNC
216216
PyInit__tracemalloc(void)
217217
{
218-
PyObject *m;
219-
m = PyModule_Create(&module_def);
220-
if (m == NULL)
218+
PyObject *mod = PyModule_Create(&module_def);
219+
if (mod == NULL) {
221220
return NULL;
221+
}
222+
222223
#ifdef Py_GIL_DISABLED
223-
PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
224+
PyUnstable_Module_SetGIL(mod, Py_MOD_GIL_NOT_USED);
224225
#endif
225226

226-
if (_PyTraceMalloc_Init() < 0) {
227-
Py_DECREF(m);
228-
return NULL;
229-
}
230-
231-
return m;
227+
return mod;
232228
}

Python/pylifecycle.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,12 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
707707
// the settings are loaded (so that feature_flags are set) but before
708708
// any calls are made to obmalloc functions.
709709
if (_PyMem_init_obmalloc(interp) < 0) {
710-
return _PyStatus_NO_MEMORY();
710+
return _PyStatus_NO_MEMORY();
711+
}
712+
713+
status = _PyTraceMalloc_Init();
714+
if (_PyStatus_EXCEPTION(status)) {
715+
return status;
711716
}
712717

713718
PyThreadState *tstate = _PyThreadState_New(interp,

0 commit comments

Comments
 (0)