1
0
mirror of https://github.com/craigerl/aprsd.git synced 2025-08-03 14:02:26 -04:00

Fix runaway KISS driver on failed connnection

This patch fixes an issue when the KISS connection fails to start
and or goes away during the lifetime of the active connection.
Aprsd would runaway in a tight loop eating 100% cpu.  We now detect
when the underlying asyncio connection has failed and raise, which
induces a sleep in the consumer to try again.
This commit is contained in:
Hemna 2025-02-15 18:55:58 -05:00
parent d82a81a2c3
commit b6da0ebb0d
2 changed files with 29 additions and 5 deletions

View File

@ -18,12 +18,13 @@ class KISS3Client:
# date for last time we heard from the server # date for last time we heard from the server
aprsd_keepalive = datetime.datetime.now() aprsd_keepalive = datetime.datetime.now()
_connected = False
def __init__(self): def __init__(self):
self.setup() self.setup()
def is_alive(self): def is_alive(self):
return True return self._connected
def setup(self): def setup(self):
# we can be TCP kiss or Serial kiss # we can be TCP kiss or Serial kiss
@ -56,17 +57,33 @@ class KISS3Client:
self.path = CONF.kiss_tcp.path self.path = CONF.kiss_tcp.path
LOG.debug('Starting KISS interface connection') LOG.debug('Starting KISS interface connection')
self.kiss.start() try:
self.kiss.start()
if self.kiss.protocol.transport.is_closing():
LOG.warning('KISS transport is closing, not setting consumer callback')
self._connected = False
else:
self._connected = True
except Exception:
LOG.error('Failed to start KISS interface.')
self._connected = False
@trace.trace @trace.trace
def stop(self): def stop(self):
if not self._connected:
# do nothing since we aren't connected
return
try: try:
self.kiss.stop() self.kiss.stop()
self.kiss.loop.call_soon_threadsafe( self.kiss.loop.call_soon_threadsafe(
self.kiss.protocol.transport.close, self.kiss.protocol.transport.close,
) )
except Exception as ex: except Exception:
LOG.exception(ex) LOG.error('Failed to stop KISS interface.')
def close(self):
self.stop()
def set_filter(self, filter): def set_filter(self, filter):
# This does nothing right now. # This does nothing right now.
@ -86,8 +103,14 @@ class KISS3Client:
LOG.exception(ex) LOG.exception(ex)
def consumer(self, callback): def consumer(self, callback):
if not self._connected:
raise Exception('KISS transport is not connected')
self._parse_callback = callback self._parse_callback = callback
self.kiss.read(callback=self.parse_frame, min_frames=None) if not self.kiss.protocol.transport.is_closing():
self.kiss.read(callback=self.parse_frame, min_frames=1)
else:
self._connected = False
def send(self, packet): def send(self, packet):
"""Send an APRS Message object.""" """Send an APRS Message object."""

View File

@ -140,3 +140,4 @@ class KISSClient(base.APRSClient):
except Exception as ex: except Exception as ex:
LOG.error(f'Consumer failed {ex}') LOG.error(f'Consumer failed {ex}')
LOG.error(ex) LOG.error(ex)
raise ex