Skip to content

Commit 00c69d2

Browse files
committed
gh-144763: Don't detach the GIL in tracemalloc
tracemalloc no longer detachs the GIL to acquire its internal lock.
1 parent 945bf8c commit 00c69d2

2 files changed

Lines changed: 12 additions & 3 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a race condition in :mod:`tracemalloc`: it no longer detachs the GIL to
2+
acquire its internal lock. Patch by Victor Stinner.

Python/tracemalloc.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ static int _PyTraceMalloc_TraceRef(PyObject *op, PyRefTracerEvent event,
3636
the GIL held from PyMem_RawFree(). It cannot acquire the lock because it
3737
would introduce a deadlock in _PyThreadState_DeleteCurrent(). */
3838
#define tables_lock _PyRuntime.tracemalloc.tables_lock
39-
#define TABLES_LOCK() PyMutex_Lock(&tables_lock)
39+
#define TABLES_LOCK() PyMutex_LockFlags(&tables_lock, _Py_LOCK_DONT_DETACH)
4040
#define TABLES_UNLOCK() PyMutex_Unlock(&tables_lock)
4141

4242

@@ -224,13 +224,20 @@ tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)
224224
assert(PyStackRef_CodeCheck(pyframe->f_executable));
225225
frame->filename = &_Py_STR(anon_unknown);
226226

227-
int lineno = PyUnstable_InterpreterFrame_GetLine(pyframe);
227+
int lineno = -1;
228+
PyCodeObject *code = _PyFrame_GetCode(pyframe);
229+
// PyUnstable_InterpreterFrame_GetLine() cannot but used, since it uses
230+
// a critical section which can trigger a deadlock.
231+
int lasti = _PyFrame_SafeGetLasti(pyframe);
232+
if (lasti >= 0) {
233+
lineno = _PyCode_SafeAddr2Line(code, lasti);
234+
}
228235
if (lineno < 0) {
229236
lineno = 0;
230237
}
231238
frame->lineno = (unsigned int)lineno;
232239

233-
PyObject *filename = _PyFrame_GetCode(pyframe)->co_filename;
240+
PyObject *filename = code->co_filename;
234241
if (filename == NULL) {
235242
#ifdef TRACE_DEBUG
236243
tracemalloc_error("failed to get the filename of the code object");

0 commit comments

Comments
 (0)