the GIL held from PyMem_RawFree(). It cannot acquire the lock because it
would introduce a deadlock in _PyThreadState_DeleteCurrent(). */
#define tables_lock _PyRuntime.tracemalloc.tables_lock
-#define TABLES_LOCK() PyMutex_Lock(&tables_lock)
+#define TABLES_LOCK() PyMutex_LockFlags(&tables_lock, _Py_LOCK_DONT_DETACH)
#define TABLES_UNLOCK() PyMutex_Unlock(&tables_lock)
assert(PyStackRef_CodeCheck(pyframe->f_executable));
frame->filename = &_Py_STR(anon_unknown);
- int lineno = PyUnstable_InterpreterFrame_GetLine(pyframe);
+ int lineno = -1;
+ PyCodeObject *code = _PyFrame_GetCode(pyframe);
+ // PyUnstable_InterpreterFrame_GetLine() cannot but used, since it uses
+ // a critical section which can trigger a deadlock.
+ int lasti = _PyFrame_SafeGetLasti(pyframe);
+ if (lasti >= 0) {
+ lineno = _PyCode_SafeAddr2Line(code, lasti);
+ }
if (lineno < 0) {
lineno = 0;
}
frame->lineno = (unsigned int)lineno;
- PyObject *filename = _PyFrame_GetCode(pyframe)->co_filename;
+ PyObject *filename = code->co_filename;
if (filename == NULL) {
#ifdef TRACE_DEBUG
tracemalloc_error("failed to get the filename of the code object");
TABLES_LOCK();
if (!tracemalloc_config.tracing) {
- goto done;
+ TABLES_UNLOCK();
+ return;
}
/* stop tracing Python memory allocations */
raw_free(tracemalloc_traceback);
tracemalloc_traceback = NULL;
- (void)PyRefTracer_SetTracer(NULL, NULL);
-
-done:
TABLES_UNLOCK();
+
+ // Call it after TABLES_UNLOCK() since it calls _PyEval_StopTheWorldAll()
+ // which would lead to a deadlock with TABLES_LOCK() which doesn't detach
+ // the thread state.
+ (void)PyRefTracer_SetTracer(NULL, NULL);
}