@@ -56,28 +56,60 @@ def __init__(
5656 buffer_size = 1 , protobuf_type = RobotStatus
5757 )
5858
59- self .blue_full_system_proto_unix_io .register_observer (
60- SSL_WrapperPacket , self .ssl_wrapper_buffer
59+ # Track every observer we register so we can clean them up later. This
60+ # matters when the runner is short-lived but the ProtoUnixIOs outlive it
61+ # (e.g. running tests repeatedly from the test selector widget).
62+ self ._registered_observers = []
63+
64+ self ._register_observer (
65+ self .blue_full_system_proto_unix_io ,
66+ SSL_WrapperPacket ,
67+ self .ssl_wrapper_buffer ,
6168 )
62- self .blue_full_system_proto_unix_io . register_observer (
63- RobotStatus , self .robot_status_buffer
69+ self ._register_observer (
70+ self . blue_full_system_proto_unix_io , RobotStatus , self .robot_status_buffer
6471 )
6572 if self .is_yellow_friendly :
66- self .yellow_full_system_proto_unix_io . register_observer (
67- World , self .world_buffer
73+ self ._register_observer (
74+ self . yellow_full_system_proto_unix_io , World , self .world_buffer
6875 )
69- self .yellow_full_system_proto_unix_io .register_observer (
70- PrimitiveSet , self .primitive_set_buffer
76+ self ._register_observer (
77+ self .yellow_full_system_proto_unix_io ,
78+ PrimitiveSet ,
79+ self .primitive_set_buffer ,
7180 )
7281 # Only validate on the blue worlds
7382 else :
74- self .blue_full_system_proto_unix_io . register_observer (
75- World , self .world_buffer
83+ self ._register_observer (
84+ self . blue_full_system_proto_unix_io , World , self .world_buffer
7685 )
77- self .blue_full_system_proto_unix_io .register_observer (
78- PrimitiveSet , self .primitive_set_buffer
86+ self ._register_observer (
87+ self .blue_full_system_proto_unix_io ,
88+ PrimitiveSet ,
89+ self .primitive_set_buffer ,
7990 )
8091
92+ def _register_observer (self , proto_unix_io , proto_class , buffer ):
93+ """Register an observer on a ProtoUnixIO and record it for cleanup.
94+
95+ :param proto_unix_io: the ProtoUnixIO to register on
96+ :param proto_class: the protobuf class to observe
97+ :param buffer: the buffer to push observed protos onto
98+ """
99+ proto_unix_io .register_observer (proto_class , buffer )
100+ self ._registered_observers .append ((proto_unix_io , proto_class , buffer ))
101+
102+ def unregister_observers (self ):
103+ """Unregister every observer this runner registered.
104+
105+ Call this when the runner is done but its ProtoUnixIOs live on, to avoid
106+ leaking stale buffers that keep receiving protos (e.g. when running tests
107+ repeatedly from the test selector widget in --test_mode).
108+ """
109+ for proto_unix_io , proto_class , buffer in self ._registered_observers :
110+ proto_unix_io .unregister_observer (proto_class , buffer )
111+ self ._registered_observers = []
112+
81113 def send_gamecontroller_command (
82114 self ,
83115 gc_command : proto .ssl_gc_state_pb2 .Command ,
0 commit comments