1
0
mirror of https://github.com/craigerl/aprsd.git synced 2025-06-13 20: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
aprsd_keepalive = datetime.datetime.now()
_connected = False
def __init__(self):
self.setup()
def is_alive(self):
return True
return self._connected
def setup(self):
# we can be TCP kiss or Serial kiss
@ -56,17 +57,33 @@ class KISS3Client:
self.path = CONF.kiss_tcp.path
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
def stop(self):
if not self._connected:
# do nothing since we aren't connected
return
try:
self.kiss.stop()
self.kiss.loop.call_soon_threadsafe(
self.kiss.protocol.transport.close,
)
except Exception as ex:
LOG.exception(ex)
except Exception:
LOG.error('Failed to stop KISS interface.')
def close(self):
self.stop()
def set_filter(self, filter):
# This does nothing right now.
@ -86,8 +103,14 @@ class KISS3Client:
LOG.exception(ex)
def consumer(self, callback):
if not self._connected:
raise Exception('KISS transport is not connected')
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):
"""Send an APRS Message object."""

View File

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