@@ -529,8 +529,6 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
529
529
530
530
if slaveargs is not None :
531
531
args , kwargs = json .loads (slaveargs )
532
- if kwargs ['huntrleaks' ]:
533
- warm_caches ()
534
532
if testdir :
535
533
kwargs ['testdir' ] = testdir
536
534
try :
@@ -541,9 +539,6 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
541
539
print json .dumps (result )
542
540
sys .exit (0 )
543
541
544
- if huntrleaks :
545
- warm_caches ()
546
-
547
542
good = []
548
543
bad = []
549
544
skipped = []
@@ -1332,7 +1327,7 @@ def runtest_inner(test, verbose, quiet, huntrleaks=False, pgo=False, testdir=Non
1332
1327
indirect_test = getattr (the_module , "test_main" , None )
1333
1328
if huntrleaks :
1334
1329
refleak = dash_R (the_module , test , indirect_test ,
1335
- huntrleaks )
1330
+ huntrleaks , quiet )
1336
1331
else :
1337
1332
if indirect_test is not None :
1338
1333
indirect_test ()
@@ -1425,7 +1420,7 @@ def cleanup_test_droppings(testname, verbose):
1425
1420
print >> sys .stderr , ("%r left behind %s %r and it couldn't be "
1426
1421
"removed: %s" % (testname , kind , name , msg ))
1427
1422
1428
- def dash_R (the_module , test , indirect_test , huntrleaks ):
1423
+ def dash_R (the_module , test , indirect_test , huntrleaks , quiet ):
1429
1424
"""Run a test multiple times, looking for reference leaks.
1430
1425
1431
1426
Returns:
@@ -1438,6 +1433,10 @@ def dash_R(the_module, test, indirect_test, huntrleaks):
1438
1433
raise Exception ("Tracking reference leaks requires a debug build "
1439
1434
"of Python" )
1440
1435
1436
+ # Avoid false positives due to various caches
1437
+ # filling slowly with random data:
1438
+ warm_caches ()
1439
+
1441
1440
# Save current values for dash_R_cleanup() to restore.
1442
1441
fs = warnings .filters [:]
1443
1442
ps = copy_reg .dispatch_table .copy ()
@@ -1457,6 +1456,14 @@ def dash_R(the_module, test, indirect_test, huntrleaks):
1457
1456
for obj in abc .__subclasses__ () + [abc ]:
1458
1457
abcs [obj ] = obj ._abc_registry .copy ()
1459
1458
1459
+ # bpo-31217: Integer pool to get a single integer object for the same
1460
+ # value. The pool is used to prevent false alarm when checking for memory
1461
+ # block leaks. Fill the pool with values in -1000..1000 which are the most
1462
+ # common (reference, memory block, file descriptor) differences.
1463
+ int_pool = {value : value for value in range (- 1000 , 1000 )}
1464
+ def get_pooled_int (value ):
1465
+ return int_pool .setdefault (value , value )
1466
+
1460
1467
if indirect_test :
1461
1468
def run_the_test ():
1462
1469
indirect_test ()
@@ -1467,27 +1474,39 @@ def run_the_test():
1467
1474
deltas = []
1468
1475
nwarmup , ntracked , fname = huntrleaks
1469
1476
fname = os .path .join (support .SAVEDCWD , fname )
1477
+
1478
+ # Pre-allocate to ensure that the loop doesn't allocate anything new
1470
1479
repcount = nwarmup + ntracked
1471
- rc_deltas = [0 ] * ntracked
1472
- fd_deltas = [0 ] * ntracked
1480
+ rc_deltas = [0 ] * repcount
1481
+ fd_deltas = [0 ] * repcount
1482
+ rep_range = list (range (repcount ))
1483
+
1484
+ if not quiet :
1485
+ print >> sys .stderr , "beginning" , repcount , "repetitions"
1486
+ print >> sys .stderr , ("1234567890" * (repcount // 10 + 1 ))[:repcount ]
1473
1487
1474
- print >> sys .stderr , "beginning" , repcount , "repetitions"
1475
- print >> sys .stderr , ("1234567890" * (repcount // 10 + 1 ))[:repcount ]
1476
1488
dash_R_cleanup (fs , ps , pic , zdc , abcs )
1489
+
1477
1490
# initialize variables to make pyflakes quiet
1478
1491
rc_before = fd_before = 0
1479
- for i in range (repcount ):
1492
+
1493
+ for i in rep_range :
1480
1494
run_the_test ()
1481
- sys .stderr .write ('.' )
1495
+
1496
+ if not quiet :
1497
+ sys .stderr .write ('.' )
1498
+
1482
1499
dash_R_cleanup (fs , ps , pic , zdc , abcs )
1500
+
1483
1501
rc_after = sys .gettotalrefcount ()
1484
1502
fd_after = support .fd_count ()
1485
- if i >= nwarmup :
1486
- rc_deltas [i - nwarmup ] = rc_after - rc_before
1487
- fd_deltas [i - nwarmup ] = fd_after - fd_before
1503
+ rc_deltas [i ] = get_pooled_int (rc_after - rc_before )
1504
+ fd_deltas [i ] = get_pooled_int (fd_after - fd_before )
1488
1505
rc_before = rc_after
1489
1506
fd_before = fd_after
1490
- print >> sys .stderr
1507
+
1508
+ if not quiet :
1509
+ print >> sys .stderr
1491
1510
1492
1511
# These checkers return False on success, True on failure
1493
1512
def check_rc_deltas (deltas ):
@@ -1513,6 +1532,7 @@ def check_fd_deltas(deltas):
1513
1532
(rc_deltas , 'references' , check_rc_deltas ),
1514
1533
(fd_deltas , 'file descriptors' , check_fd_deltas )
1515
1534
]:
1535
+ deltas = deltas [nwarmup :]
1516
1536
if checker (deltas ):
1517
1537
msg = '%s leaked %s %s, sum=%s' % (test , deltas , item_name , sum (deltas ))
1518
1538
print >> sys .stderr , msg
@@ -1647,7 +1667,7 @@ def clear_caches():
1647
1667
ctypes ._reset_cache ()
1648
1668
1649
1669
# Collect cyclic trash.
1650
- gc . collect ()
1670
+ support . gc_collect ()
1651
1671
1652
1672
def warm_caches ():
1653
1673
"""Create explicitly internal singletons which are created on demand
0 commit comments