Fix a few eventlet leftovers in the code

There were still a couple of places where the threading
code was using eventlet. Cleaned them up along with some
other test issues noticed during debugging.

Add a definition for cancel() to HubThread class in
native code as it is called when threads are stopped in
the BGP peer code.

Use hub.kill(thread) to kill threads instead of
thread.kill() as it will use hub-specific logic.

Add a stop() method to BGP Peer class so users can stop
any threads that might have been started in __init__(),
like the periodic stats logger.

Do not use eventlet to spawn threads in BGP code, always
use self._spawn() which uses hub-specific code.

Use hub.Semaphore class in bgp/speaker.py which uses the
hub-specific semaphore code.

Change BGP peer "looped" tests to not enable the periodic
stats logging thread since it is unnecessary, and
would require a call to the class stop() method on exit.

Related-bug: #2087939
Change-Id: Ib2a1e12a2d5d25ede1cc1678d23e88ceae822b31
Signed-off-by: Brian Haley <haleyb.dev@gmail.com>
This commit is contained in:
Brian Haley
2025-10-31 11:17:18 -04:00
parent 12b0b870b8
commit 8195cd818c
6 changed files with 15 additions and 14 deletions

View File

@@ -274,6 +274,9 @@ elif HUB_TYPE == 'native':
LOG.error('HubThread uncaught exception: %s',
traceback.format_exc())
def cancel(self):
pass
def spawn(func, *args, **kwargs):
thread = HubThread(func, args, kwargs)
thread.start()

View File

@@ -285,7 +285,7 @@ class Activity(object, metaclass=abc.ABCMeta):
if name is None or thread_name == name:
LOG.debug('%s: Stopping child thread %s',
self.name, thread_name)
thread.kill()
hub.kill(thread)
self._child_thread_map.pop(thread_name, None)
def _close_asso_sockets(self):
@@ -386,16 +386,8 @@ class Activity(object, metaclass=abc.ABCMeta):
for sa in listen_sockets:
name = self.name + '_server@' + str(sa[0])
self._asso_socket_map[name] = listen_sockets[sa]
if count == 0:
import eventlet
server = eventlet.spawn(self._listen_socket_loop,
listen_sockets[sa], conn_handle)
self._child_thread_map[name] = server
count += 1
else:
server = self._spawn(name, self._listen_socket_loop,
listen_sockets[sa], conn_handle)
server = self._spawn(name, self._listen_socket_loop,
listen_sockets[sa], conn_handle)
return server, listen_sockets
def _connect_tcp(self, peer_addr, conn_handler, time_out=None,

View File

@@ -682,6 +682,11 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
# Start sink processing
self._process_outgoing_msg_list()
def stop(self):
LOG.debug('Stopped peer %s', self)
if self._neigh_conf.stats_log_enabled:
self._periodic_stats_logger.stop()
def _send_outgoing_route_refresh_msg(self, rr_msg):
"""Sends given message `rr_msg` to peer.

View File

@@ -21,8 +21,8 @@ import socket
import struct
import traceback
from socket import IPPROTO_TCP, TCP_NODELAY
from eventlet import semaphore
from os_ken.lib import hub
from os_ken.lib.packet import bgp
from os_ken.lib.packet.bgp import AS_TRANS
from os_ken.lib.packet.bgp import BGPMessage
@@ -105,7 +105,7 @@ class BgpProtocol(Protocol, Activity):
self._recv_buff = b''
self._socket = socket
self._socket.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1)
self._sendlock = semaphore.Semaphore()
self._sendlock = hub.Semaphore()
self._signal_bus = signal_bus
self._holdtime = None
self._keepalive = None

View File

@@ -355,7 +355,7 @@ class RouterIPV4Linux(RouterIPV4):
def _disable_router(self):
if self._arp_thread is not None:
self._arp_thread.kill()
hub.kill(self._arp_thread)
hub.joinall([self._arp_thread])
self._arp_thread = None
# TODO: implement real routing logic

View File

@@ -377,6 +377,7 @@ class Test_Peer(unittest.TestCase):
neigh_conf = mock.Mock()
neigh_conf.local_as = local_as
neigh_conf.stats_time = 0
neigh_conf.stats_log_enabled = False
common_conf = mock.Mock()
common_conf.allow_local_as_in_count = allow_local_as_in_count
common_conf.cluster_id = '10.0.0.1'