11import contextlib
22import os
33import sys
4+ import textwrap
45import tracemalloc
56import unittest
67from unittest .mock import patch
1920 _testinternalcapi = None
2021
2122
23+ DEFAULT_DOMAIN = 0
2224EMPTY_STRING_SIZE = sys .getsizeof (b'' )
2325INVALID_NFRAME = (- 1 , 2 ** 30 )
2426
@@ -1027,8 +1029,8 @@ def track(self, release_gil=False, nframe=1):
10271029 release_gil )
10281030 return frames
10291031
1030- def untrack (self ):
1031- _testcapi .tracemalloc_untrack (self .domain , self .ptr )
1032+ def untrack (self , release_gil = False ):
1033+ _testcapi .tracemalloc_untrack (self .domain , self .ptr , release_gil )
10321034
10331035 def get_traced_memory (self ):
10341036 # Get the traced size in the domain
@@ -1070,21 +1072,27 @@ def test_track_already_tracked(self):
10701072 self .assertEqual (self .get_traceback (),
10711073 tracemalloc .Traceback (frames ))
10721074
1073- def test_untrack (self ):
1075+ def check_untrack (self , release_gil ):
10741076 tracemalloc .start ()
10751077
10761078 self .track ()
10771079 self .assertIsNotNone (self .get_traceback ())
10781080 self .assertEqual (self .get_traced_memory (), self .size )
10791081
10801082 # untrack must remove the trace
1081- self .untrack ()
1083+ self .untrack (release_gil )
10821084 self .assertIsNone (self .get_traceback ())
10831085 self .assertEqual (self .get_traced_memory (), 0 )
10841086
10851087 # calling _PyTraceMalloc_Untrack() multiple times must not crash
1086- self .untrack ()
1087- self .untrack ()
1088+ self .untrack (release_gil )
1089+ self .untrack (release_gil )
1090+
1091+ def test_untrack (self ):
1092+ self .check_untrack (False )
1093+
1094+ def test_untrack_without_gil (self ):
1095+ self .check_untrack (True )
10881096
10891097 def test_stop_track (self ):
10901098 tracemalloc .start ()
@@ -1110,6 +1118,29 @@ def test_tracemalloc_track_race(self):
11101118 # gh-128679: Test fix for tracemalloc.stop() race condition
11111119 _testcapi .tracemalloc_track_race ()
11121120
1121+ def test_late_untrack (self ):
1122+ code = textwrap .dedent (f"""
1123+ from test import support
1124+ import tracemalloc
1125+ import _testcapi
1126+
1127+ class Tracked:
1128+ def __init__(self, domain, size):
1129+ self.domain = domain
1130+ self.ptr = id(self)
1131+ self.size = size
1132+ _testcapi.tracemalloc_track(self.domain, self.ptr, self.size)
1133+
1134+ def __del__(self, untrack=_testcapi.tracemalloc_untrack):
1135+ untrack(self.domain, self.ptr, 1)
1136+
1137+ domain = { DEFAULT_DOMAIN }
1138+ tracemalloc.start()
1139+ obj = Tracked(domain, 1024 * 1024)
1140+ support.late_deletion(obj)
1141+ """ )
1142+ assert_python_ok ("-c" , code )
1143+
11131144
11141145if __name__ == "__main__" :
11151146 unittest .main ()
0 commit comments