From 973d08a5f65c99d00dcf1451ba0b04984486a607 Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Thu, 9 Jan 2025 18:10:09 -0500 Subject: [PATCH 1/3] gh-128679: fix race condition in tracemalloc --- Python/tracemalloc.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/Python/tracemalloc.c b/Python/tracemalloc.c index f661d69c0312fa..d2e3dfc53ba22f 100644 --- a/Python/tracemalloc.c +++ b/Python/tracemalloc.c @@ -538,11 +538,13 @@ tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize) return NULL; TABLES_LOCK(); - if (ADD_TRACE(ptr, nelem * elsize) < 0) { - /* Failed to allocate a trace for the new memory block */ - TABLES_UNLOCK(); - alloc->free(alloc->ctx, ptr); - return NULL; + if (tracemalloc_config.tracing) { + if (ADD_TRACE(ptr, nelem * elsize) < 0) { + /* Failed to allocate a trace for the new memory block */ + TABLES_UNLOCK(); + alloc->free(alloc->ctx, ptr); + return NULL; + } } TABLES_UNLOCK(); return ptr; @@ -963,8 +965,11 @@ _PyTraceMalloc_Stop(void) if (!tracemalloc_config.tracing) return; - /* stop tracing Python memory allocations */ + /* stop tracing Python memory allocations, + but not while something might be in the middle of an operation */ + TABLES_LOCK(); tracemalloc_config.tracing = 0; + TABLES_UNLOCK(); /* unregister the hook on memory allocators */ #ifdef TRACE_RAW_MALLOC @@ -1317,6 +1322,12 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, gil_state = PyGILState_Ensure(); + if (!tracemalloc_config.tracing) { + /* tracing may have been turned off as we were acquiring the GIL */ + PyGILState_Release(gil_state); + return -2; + } + TABLES_LOCK(); res = tracemalloc_add_trace(domain, ptr, size); TABLES_UNLOCK(); From 170cf149c764793627c0ef2f2c1fe32a3b0b96d4 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 9 Jan 2025 23:25:43 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2025-01-09-23-25-42.gh-issue-128679.Uhblds.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-01-09-23-25-42.gh-issue-128679.Uhblds.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-09-23-25-42.gh-issue-128679.Uhblds.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-09-23-25-42.gh-issue-128679.Uhblds.rst new file mode 100644 index 00000000000000..b510b19a5c5652 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-09-23-25-42.gh-issue-128679.Uhblds.rst @@ -0,0 +1 @@ +Fix race condition in tracemalloc causing abort. From a85a298ced8f0bde4cdef9375f0e193613c28745 Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Fri, 10 Jan 2025 08:43:18 -0500 Subject: [PATCH 3/3] add requested comment --- Python/tracemalloc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Python/tracemalloc.c b/Python/tracemalloc.c index d2e3dfc53ba22f..a48b0fcf4817b3 100644 --- a/Python/tracemalloc.c +++ b/Python/tracemalloc.c @@ -538,6 +538,13 @@ tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize) return NULL; TABLES_LOCK(); + /* This operation can be executed outside of GIL protection due to + allocations needed for an initial PyGILState_Ensure(). Because of this, + tracing may be turned off concurrently in another thread which currently + holds the GIL between the initial check of `tracing` variable and here. + This is a sanity check to account for this possibility and avoid a + potential abort where it can be handled gracefully instead. + See gh-128679. */ if (tracemalloc_config.tracing) { if (ADD_TRACE(ptr, nelem * elsize) < 0) { /* Failed to allocate a trace for the new memory block */