@@ -1270,8 +1270,16 @@ def set_memlimit(limit: str) -> None:
12701270 max_memuse = memlimit
12711271
12721272
1273+ def _memory_limit (nbytes ):
1274+ """How much memory a test declaring *nbytes* may use.
1275+
1276+ The interpreter itself reserves about 250 MiB, whatever the test asks for.
1277+ """
1278+ return int (nbytes ) + 512 * _1M
1279+
1280+
12731281def _limit_address_space (nbytes ):
1274- """Limit the address space of this process to *nbytes* plus a margin .
1282+ """Limit the address space of this process to what a test may use .
12751283
12761284 A test which uses much more memory than it declares then fails with a
12771285 MemoryError instead of making the machine swap.
@@ -1280,32 +1288,43 @@ def _limit_address_space(nbytes):
12801288 # AddressSanitizer reserves terabytes of address space for its shadow
12811289 # memory, so any limit stops the interpreter from starting.
12821290 return
1291+ if sys .platform == 'darwin' :
1292+ # macOS reserves much more address space than it uses.
1293+ return
12831294 try :
12841295 import resource
12851296 rlimit = resource .RLIMIT_AS
12861297 except (ImportError , AttributeError ):
12871298 return
1288- # The margin does not grow with the declared size: the interpreter itself
1289- # reserves about 250 MiB, whatever the test asks for. macOS reserves more.
1290- margin = _1G if sys .platform == 'darwin' else 512 * _1M
1291- limit = int (nbytes ) + margin
1299+ limit = _memory_limit (nbytes )
12921300 soft , hard = resource .getrlimit (rlimit )
12931301 for current in soft , hard :
12941302 if current != resource .RLIM_INFINITY :
12951303 limit = min (limit , current )
12961304 resource .setrlimit (rlimit , (limit , hard ))
12971305
12981306
1299- def _memory_watchdog (pid ):
1300- """Return a function printing the memory usage of process *pid*."""
1307+ def _memory_watchdog (proc , limit ):
1308+ """Return a function watching the memory used by the test in *proc*.
1309+
1310+ It reports the usage in verbose mode, and kills the test if it uses more
1311+ than *limit* bytes. This is the only limit where the address space cannot
1312+ be limited.
1313+ """
13011314 # Imported here: test.support does not depend on test.libregrtest.
13021315 from test .libregrtest .utils import get_process_memory_usage
13031316
13041317 def watch ():
1305- mem = get_process_memory_usage (pid )
1306- if mem is not None :
1318+ mem = get_process_memory_usage (proc .pid )
1319+ if mem is None :
1320+ return
1321+ if verbose :
13071322 print (f" ... process data size: { mem / (1024 ** 3 ):.1f} GiB" ,
13081323 flush = True )
1324+ if limit is not None and mem > limit :
1325+ watch .exceeded = mem
1326+ proc .kill ()
1327+ watch .exceeded = None
13091328 return watch
13101329
13111330
@@ -1364,8 +1383,17 @@ def wrapper(self):
13641383 cls = type (self )
13651384 qualname = f'{ cls .__qualname__ } .{ f .__name__ } '
13661385 proc = isolation ._start_test (cls .__module__ , qualname )
1367- watchdog = _memory_watchdog (proc .pid ) if verbose else None
1368- isolation ._replay_test (self , * proc .wait (tick = watchdog ))
1386+ # Watched even if the address space is not limited: this
1387+ # counts the memory really used.
1388+ watchdog = _memory_watchdog (proc ,
1389+ _memory_limit (size * memuse ))
1390+ payload , output , returncode = proc .wait (tick = watchdog )
1391+ if watchdog .exceeded :
1392+ raise AssertionError (
1393+ f'the test used { watchdog .exceeded / _1G :.1f} GiB, '
1394+ f'more than the { size * memuse / _1G :.1f} GiB '
1395+ f'it declares' )
1396+ isolation ._replay_test (self , payload , output , returncode )
13691397 return
13701398
13711399 if (real_max_memuse and limit_address_space
0 commit comments