@@ -456,15 +456,13 @@ tracemalloc_add_trace(void *ptr, size_t size)
456456 trace .size = size ;
457457 trace .traceback = traceback ;
458458
459- TABLES_LOCK ();
460459 res = _Py_HASHTABLE_SET (tracemalloc_traces , ptr , trace );
461460 if (res == 0 ) {
462461 assert (tracemalloc_traced_memory <= PY_SIZE_MAX - size );
463462 tracemalloc_traced_memory += size ;
464463 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory )
465464 tracemalloc_peak_traced_memory = tracemalloc_traced_memory ;
466465 }
467- TABLES_UNLOCK ();
468466
469467 return res ;
470468}
@@ -474,12 +472,10 @@ tracemalloc_remove_trace(void *ptr)
474472{
475473 trace_t trace ;
476474
477- TABLES_LOCK ();
478475 if (_Py_hashtable_pop (tracemalloc_traces , ptr , & trace , sizeof (trace ))) {
479476 assert (tracemalloc_traced_memory >= trace .size );
480477 tracemalloc_traced_memory -= trace .size ;
481478 }
482- TABLES_UNLOCK ();
483479}
484480
485481static void *
@@ -492,11 +488,14 @@ tracemalloc_malloc(void *ctx, size_t size)
492488 if (ptr == NULL )
493489 return NULL ;
494490
491+ TABLES_LOCK ();
495492 if (tracemalloc_add_trace (ptr , size ) < 0 ) {
496493 /* Failed to allocate a trace for the new memory block */
494+ TABLES_UNLOCK ();
497495 alloc -> free (alloc -> ctx , ptr );
498496 return NULL ;
499497 }
498+ TABLES_UNLOCK ();
500499 return ptr ;
501500}
502501
@@ -513,26 +512,34 @@ tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
513512 if (ptr != NULL ) {
514513 /* an existing memory block has been resized */
515514
515+ TABLES_LOCK ();
516516 tracemalloc_remove_trace (ptr );
517517
518518 if (tracemalloc_add_trace (ptr2 , new_size ) < 0 ) {
519519 /* Memory allocation failed. The error cannot be reported to
520520 the caller, because realloc() may already have shrinked the
521521 memory block and so removed bytes.
522522
523- This case is very unlikely since we just released an hash
524- entry, so we have enough free bytes to allocate the new
525- entry. */
523+ This case is very unlikely: an hash entry has just been
524+ released, so the hash table should have at least one free entry.
525+
526+ The GIL and the table lock ensures that only one thread is
527+ allocating memory. */
528+ assert (0 && "should never happen" );
526529 }
530+ TABLES_UNLOCK ();
527531 }
528532 else {
529533 /* new allocation */
530534
535+ TABLES_LOCK ();
531536 if (tracemalloc_add_trace (ptr2 , new_size ) < 0 ) {
532537 /* Failed to allocate a trace for the new memory block */
538+ TABLES_UNLOCK ();
533539 alloc -> free (alloc -> ctx , ptr2 );
534540 return NULL ;
535541 }
542+ TABLES_UNLOCK ();
536543 }
537544 return ptr2 ;
538545}
@@ -549,7 +556,10 @@ tracemalloc_free(void *ctx, void *ptr)
549556 a deadlock in PyThreadState_DeleteCurrent(). */
550557
551558 alloc -> free (alloc -> ctx , ptr );
559+
560+ TABLES_LOCK ();
552561 tracemalloc_remove_trace (ptr );
562+ TABLES_UNLOCK ();
553563}
554564
555565static void *
@@ -586,8 +596,11 @@ tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
586596 PyMemAllocator * alloc = (PyMemAllocator * )ctx ;
587597
588598 ptr2 = alloc -> realloc (alloc -> ctx , ptr , new_size );
589- if (ptr2 != NULL && ptr != NULL )
599+ if (ptr2 != NULL && ptr != NULL ) {
600+ TABLES_LOCK ();
590601 tracemalloc_remove_trace (ptr );
602+ TABLES_UNLOCK ();
603+ }
591604 return ptr2 ;
592605 }
593606
@@ -646,9 +659,12 @@ tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
646659 PyMemAllocator * alloc = (PyMemAllocator * )ctx ;
647660
648661 ptr2 = alloc -> realloc (alloc -> ctx , ptr , new_size );
649- if (ptr2 != NULL && ptr != NULL )
650- tracemalloc_remove_trace (ptr );
651662
663+ if (ptr2 != NULL && ptr != NULL ) {
664+ TABLES_LOCK ();
665+ tracemalloc_remove_trace (ptr );
666+ TABLES_UNLOCK ();
667+ }
652668 return ptr2 ;
653669 }
654670
0 commit comments