[Python-checkins] cpython: Close #19741: tracemalloc_realloc() does not release the table lock anymore
victor.stinner
python-checkins at python.org
Wed Dec 4 01:48:04 CET 2013
http://hg.python.org/cpython/rev/3c34ab550358
changeset: 87749:3c34ab550358
user: Victor Stinner <victor.stinner at gmail.com>
date: Wed Dec 04 01:47:46 2013 +0100
summary:
Close #19741: tracemalloc_realloc() does not release the table lock anymore
between tracemalloc_remove_trace() and tracemalloc_add_trace() to reduce the
risk of race condition.
tracemalloc_add_trace() cannot fail anymore in tracemalloc_realloc() when
tracemalloc_realloc() resizes a memory block.
files:
Modules/_tracemalloc.c | 36 +++++++++++++++++++++--------
1 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c
--- a/Modules/_tracemalloc.c
+++ b/Modules/_tracemalloc.c
@@ -456,7 +456,6 @@
trace.size = size;
trace.traceback = traceback;
- TABLES_LOCK();
res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
if (res == 0) {
assert(tracemalloc_traced_memory <= PY_SIZE_MAX - size);
@@ -464,7 +463,6 @@
if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
}
- TABLES_UNLOCK();
return res;
}
@@ -474,12 +472,10 @@
{
trace_t trace;
- TABLES_LOCK();
if (_Py_hashtable_pop(tracemalloc_traces, ptr, &trace, sizeof(trace))) {
assert(tracemalloc_traced_memory >= trace.size);
tracemalloc_traced_memory -= trace.size;
}
- TABLES_UNLOCK();
}
static void*
@@ -492,11 +488,14 @@
if (ptr == NULL)
return NULL;
+ TABLES_LOCK();
if (tracemalloc_add_trace(ptr, size) < 0) {
/* Failed to allocate a trace for the new memory block */
+ TABLES_UNLOCK();
alloc->free(alloc->ctx, ptr);
return NULL;
}
+ TABLES_UNLOCK();
return ptr;
}
@@ -513,6 +512,7 @@
if (ptr != NULL) {
/* an existing memory block has been resized */
+ TABLES_LOCK();
tracemalloc_remove_trace(ptr);
if (tracemalloc_add_trace(ptr2, new_size) < 0) {
@@ -520,19 +520,26 @@
the caller, because realloc() may already have shrinked the
memory block and so removed bytes.
- This case is very unlikely since we just released an hash
- entry, so we have enough free bytes to allocate the new
- entry. */
+ This case is very unlikely: an hash entry has just been
+ released, so the hash table should have at least one free entry.
+
+ The GIL and the table lock ensures that only one thread is
+ allocating memory. */
+ assert(0 && "should never happen");
}
+ TABLES_UNLOCK();
}
else {
/* new allocation */
+ TABLES_LOCK();
if (tracemalloc_add_trace(ptr2, new_size) < 0) {
/* Failed to allocate a trace for the new memory block */
+ TABLES_UNLOCK();
alloc->free(alloc->ctx, ptr2);
return NULL;
}
+ TABLES_UNLOCK();
}
return ptr2;
}
@@ -549,7 +556,10 @@
a deadlock in PyThreadState_DeleteCurrent(). */
alloc->free(alloc->ctx, ptr);
+
+ TABLES_LOCK();
tracemalloc_remove_trace(ptr);
+ TABLES_UNLOCK();
}
static void*
@@ -586,8 +596,11 @@
PyMemAllocator *alloc = (PyMemAllocator *)ctx;
ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
- if (ptr2 != NULL && ptr != NULL)
+ if (ptr2 != NULL && ptr != NULL) {
+ TABLES_LOCK();
tracemalloc_remove_trace(ptr);
+ TABLES_UNLOCK();
+ }
return ptr2;
}
@@ -646,9 +659,12 @@
PyMemAllocator *alloc = (PyMemAllocator *)ctx;
ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
- if (ptr2 != NULL && ptr != NULL)
+
+ if (ptr2 != NULL && ptr != NULL) {
+ TABLES_LOCK();
tracemalloc_remove_trace(ptr);
-
+ TABLES_UNLOCK();
+ }
return ptr2;
}
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list