qa: Intermittent failure in `p2p_eviction.py` #36533

issue hebasto opened this issue on October 15, 2026
  1. hebasto commented at 5:19 AM on October 15, 2026: member

    https://github.com/bitcoin/bitcoin/actions/runs/38678030191/job/116235980574:

    367/497 - p2p_eviction.py failed (exit code 1), Duration: 1 s
    
    stdout:
    2026-10-15T03:57:38.655914Z TestFramework (INFO): PRNG seed is: 7665210796316295926
    2026-10-15T03:57:38.706216Z TestFramework (INFO): Initializing test directory /tmp/test_runner_₿_🏃_20261015_035617/p2p_eviction_126
    2026-10-15T03:57:38.989690Z TestFramework (INFO): Create 4 peers and protect them from eviction by sending us a block
    2026-10-15T03:57:39.416125Z TestFramework (INFO): Create 5 slow-pinging peers, making them eviction candidates
    2026-10-15T03:57:39.930086Z TestFramework (INFO): Create 4 peers and protect them from eviction by sending us a tx
    2026-10-15T03:57:40.344877Z TestFramework (INFO): Create 8 peers and protect them from eviction by having faster pings
    2026-10-15T03:57:40.361164Z TestFramework (INFO): Create peer that triggers the eviction mechanism
    2026-10-15T03:57:40.474285Z TestFramework (INFO): Test that one peer was evicted
    2026-10-15T03:57:40.475103Z TestFramework (ERROR): Unexpected exception:
    Traceback (most recent call last):
      File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/test_framework.py", line 146, in main
        self.run_test()
      File "/home/runner/work/bitcoin/bitcoin/ci_build/test/functional/p2p_eviction.py", line 120, in run_test
        assert_equal(len(evicted_peers), 1)
      File "/home/runner/work/bitcoin/bitcoin/test/functional/test_framework/util.py", line 95, in assert_equal
        raise AssertionError("not(%s)" % " == ".join(str(arg) for arg in (thing1, thing2) + args))
    AssertionError: not(0 == 1)
    2026-10-15T03:57:40.526095Z TestFramework (INFO): Not stopping nodes as test failed. The dangling processes will be cleaned up later.
    2026-10-15T03:57:40.526190Z TestFramework (WARNING): Not cleaning up dir /tmp/test_runner_₿_🏃_20261015_035617/p2p_eviction_126
    2026-10-15T03:57:40.526218Z TestFramework (ERROR): Test failed. Test logging available at /tmp/test_runner_₿_🏃_20261015_035617/p2p_eviction_126/test_framework.log
    2026-10-15T03:57:40.526288Z TestFramework (ERROR): 
    2026-10-15T03:57:40.526345Z TestFramework (ERROR): Hint: Call /home/runner/work/bitcoin/bitcoin/test/functional/combine_logs.py '/tmp/test_runner_₿_🏃_20261015_035617/p2p_eviction_126' to consolidate all logs
    2026-10-15T03:57:40.526364Z TestFramework (ERROR): 
    2026-10-15T03:57:40.526379Z TestFramework (ERROR): If this failure happened unexpectedly or intermittently, please file a bug and provide a link or upload of the combined log.
    2026-10-15T03:57:40.526412Z TestFramework (ERROR): https://github.com/bitcoin/bitcoin/issues
    2026-10-15T03:57:40.526428Z TestFramework (ERROR): 
    
    
    stderr:
    [node 0] Cleaning up leftover process
    
    
    
  2. hebasto added the label CI failed on Oct 15, 2026
  3. maflcko commented at 3:02 PM on October 15, 2026: member

    Interesting. I would have assumed that the disconnect from the eviction is synchronised from the connection's double-ping. However, those are different sockets, so the Python asyncio thread can learn about the closed socket later than the successful connection 🤷‍♂️

    repro diff:

    diff --git a/test/functional/p2p_eviction.py b/test/functional/p2p_eviction.py
    index f297b8f39f..e4789887eb 100755
    --- a/test/functional/p2p_eviction.py
    +++ b/test/functional/p2p_eviction.py
    @@ -14,2 +14,3 @@ Therefore, this test is limited to the remaining protection criteria.
     """
    +import threading
     import time
    @@ -59,2 +60,15 @@ class P2PEvict(BitcoinTestFramework):
             self.wallet = MiniWallet(node)
    +        disconnect_started = threading.Event()
    +        allow_disconnect = threading.Event()
    +
    +        def gate_connection_lost(peer):
    +            connection_lost = peer.connection_lost
    +
    +            def delayed_connection_lost(exc):
    +                disconnect_started.set()
    +                assert allow_disconnect.wait(timeout=10)
    +                connection_lost(exc)
    +
    +            peer.connection_lost = delayed_connection_lost
    +            return peer
     
    @@ -62,3 +76,3 @@ class P2PEvict(BitcoinTestFramework):
             for _ in range(4):
    -            block_peer = node.add_p2p_connection(SlowP2PDataStore())
    +            block_peer = node.add_p2p_connection(gate_connection_lost(SlowP2PDataStore()))
                 current_peer += 1
    @@ -75,3 +89,3 @@ class P2PEvict(BitcoinTestFramework):
             for _ in range(5):
    -            node.add_p2p_connection(SlowP2PInterface())
    +            node.add_p2p_connection(gate_connection_lost(SlowP2PInterface()))
                 current_peer += 1
    @@ -80,3 +94,3 @@ class P2PEvict(BitcoinTestFramework):
             for i in range(4):
    -            txpeer = node.add_p2p_connection(SlowP2PInterface())
    +            txpeer = node.add_p2p_connection(gate_connection_lost(SlowP2PInterface()))
                 current_peer += 1
    @@ -90,3 +104,3 @@ class P2PEvict(BitcoinTestFramework):
             for _ in range(8):
    -            fastpeer = node.add_p2p_connection(P2PInterface())
    +            fastpeer = node.add_p2p_connection(gate_connection_lost(P2PInterface()))
                 current_peer += 1
    @@ -107,3 +121,6 @@ class P2PEvict(BitcoinTestFramework):
             self.log.info("Create peer that triggers the eviction mechanism")
    -        node.add_p2p_connection(SlowP2PInterface())
    +        node.add_p2p_connection(SlowP2PInterface(), wait_for_verack=False)
    +        assert disconnect_started.wait(timeout=10)
    +        allow_disconnect.set()
    +
     
    @@ -112,2 +129,3 @@ class P2PEvict(BitcoinTestFramework):
             # and the eviction mechanism doesn't preserve the order of identical elements.
    +        # This is the fix: self.wait_until(lambda: sum(not peer.is_connected for peer in node.p2ps) == 1)
             evicted_peers = []
    @@ -116,2 +134,3 @@ class P2PEvict(BitcoinTestFramework):
                     evicted_peers.append(i)
    +        allow_disconnect.set()
     
    
  4. fanquake closed this on Oct 16, 2026

  5. fanquake referenced this in commit 87fbedf5f8 on Oct 16, 2026

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-10-21 18:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me