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