Skip to content

Commit a1ea2fe

Browse files
committed
gh-129185: Fix PyTraceMalloc_Untrack() at Python exit
Support calling PyTraceMalloc_Track() and PyTraceMalloc_Untrack() during late Python finalization.
1 parent 1885988 commit a1ea2fe

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

Lib/test/test_tracemalloc.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import contextlib
22
import os
33
import sys
4+
import textwrap
45
import tracemalloc
56
import unittest
67
from unittest.mock import patch
@@ -19,6 +20,7 @@
1920
_testinternalcapi = None
2021

2122

23+
DEFAULT_DOMAIN = 0
2224
EMPTY_STRING_SIZE = sys.getsizeof(b'')
2325
INVALID_NFRAME = (-1, 2**30)
2426

@@ -1110,6 +1112,29 @@ def test_tracemalloc_track_race(self):
11101112
# gh-128679: Test fix for tracemalloc.stop() race condition
11111113
_testcapi.tracemalloc_track_race()
11121114

1115+
def test_late_untrack(self):
1116+
code = textwrap.dedent(f"""
1117+
from test import support
1118+
import tracemalloc
1119+
import _testcapi
1120+
1121+
class Tracked:
1122+
def __init__(self, domain, size):
1123+
self.domain = domain
1124+
self.ptr = id(self)
1125+
self.size = size
1126+
_testcapi.tracemalloc_track(self.domain, self.ptr, self.size)
1127+
1128+
def __del__(self, untrack=_testcapi.tracemalloc_untrack):
1129+
untrack(self.domain, self.ptr)
1130+
1131+
domain = {DEFAULT_DOMAIN}
1132+
tracemalloc.start()
1133+
obj = Tracked(domain, 1024 * 1024)
1134+
support.late_deletion(obj)
1135+
""")
1136+
assert_python_ok("-c", code)
1137+
11131138

11141139
if __name__ == "__main__":
11151140
unittest.main()

Python/tracemalloc.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,11 @@ int
12551255
PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
12561256
size_t size)
12571257
{
1258+
// gh-129185: Pre-check to support calls after _PyTraceMalloc_Fini()
1259+
if (!tracemalloc_config.tracing) {
1260+
return -2;
1261+
}
1262+
12581263
PyGILState_STATE gil_state = PyGILState_Ensure();
12591264
TABLES_LOCK();
12601265

@@ -1277,6 +1282,11 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
12771282
int
12781283
PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
12791284
{
1285+
// gh-129185: Pre-check to support calls after _PyTraceMalloc_Fini()
1286+
if (!tracemalloc_config.tracing) {
1287+
return -2;
1288+
}
1289+
12801290
TABLES_LOCK();
12811291

12821292
int result;

0 commit comments

Comments
 (0)