Skip to content

Commit 17ebde5

Browse files
committed
Fix tracemalloc_alloc/realloc() reentrant call
1 parent fd2c44c commit 17ebde5

File tree

1 file changed

+39
-23
lines changed

1 file changed

+39
-23
lines changed

Python/tracemalloc.c

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,20 @@ tracemalloc_alloc(int need_gil, int use_calloc,
531531
{
532532
assert(elsize == 0 || nelem <= SIZE_MAX / elsize);
533533

534+
int reentrant = get_reentrant();
535+
536+
// Ignore reentrant call.
537+
//
538+
// For example, PyObjet_Malloc() calls
539+
// PyMem_Malloc() for allocations larger than 512 bytes: don't trace the
540+
// same memory allocation twice.
541+
//
542+
// If reentrant calls are not ignored, PyGILState_Ensure() can call
543+
// PyMem_RawMalloc() which would call PyGILState_Ensure() again in a loop.
544+
if (!reentrant) {
545+
set_reentrant(1);
546+
}
547+
534548
PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
535549
void *ptr;
536550
if (use_calloc) {
@@ -541,22 +555,12 @@ tracemalloc_alloc(int need_gil, int use_calloc,
541555
}
542556

543557
if (ptr == NULL) {
544-
return NULL;
558+
goto done;
545559
}
546-
if (get_reentrant()) {
547-
return ptr;
560+
if (reentrant) {
561+
goto done;
548562
}
549563

550-
// Ignore reentrant call.
551-
//
552-
// For example, PyObjet_Malloc() calls
553-
// PyMem_Malloc() for allocations larger than 512 bytes: don't trace the
554-
// same memory allocation twice.
555-
//
556-
// If reentrant calls are not ignored, PyGILState_Ensure() can call
557-
// PyMem_RawMalloc() which would call PyGILState_Ensure() again in a loop.
558-
set_reentrant(1);
559-
560564
PyGILState_STATE gil_state;
561565
if (need_gil) {
562566
gil_state = PyGILState_Ensure();
@@ -573,29 +577,37 @@ tracemalloc_alloc(int need_gil, int use_calloc,
573577
if (need_gil) {
574578
PyGILState_Release(gil_state);
575579
}
576-
set_reentrant(0);
580+
581+
done:
582+
if (!reentrant) {
583+
set_reentrant(0);
584+
}
577585
return ptr;
578586
}
579587

580588

581589
static void*
582590
tracemalloc_realloc(int need_gil, void *ctx, void *ptr, size_t new_size)
583591
{
592+
int reentrant = get_reentrant();
593+
594+
// Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
595+
// allocations larger than 512 bytes: don't trace the same memory block
596+
// twice.
597+
if (!reentrant) {
598+
set_reentrant(1);
599+
}
600+
584601
PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
585602
void *ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
586603

587604
if (ptr2 == NULL) {
588-
return NULL;
605+
goto done;
589606
}
590-
if (get_reentrant()) {
591-
return ptr2;
607+
if (reentrant) {
608+
goto done;
592609
}
593610

594-
// Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
595-
// allocations larger than 512 bytes: don't trace the same memory block
596-
// twice.
597-
set_reentrant(1);
598-
599611
PyGILState_STATE gil_state;
600612
if (need_gil) {
601613
gil_state = PyGILState_Ensure();
@@ -638,7 +650,11 @@ tracemalloc_realloc(int need_gil, void *ctx, void *ptr, size_t new_size)
638650
if (need_gil) {
639651
PyGILState_Release(gil_state);
640652
}
641-
set_reentrant(0);
653+
654+
done:
655+
if (!reentrant) {
656+
set_reentrant(0);
657+
}
642658
return ptr2;
643659
}
644660

0 commit comments

Comments
 (0)