fix: health monitor disables SSID pool immediately on PING failure

Ring-buffer SIGSEGV counts were unreliable for growth detection; the pool
broadcast is the only known crash cause, so disable it on first failure.
This commit is contained in:
2026-08-18 19:32:49 -05:00
parent 2ff0c4d320
commit a4285496fb
2 changed files with 20 additions and 11 deletions
@@ -3205,7 +3205,11 @@ def _monitor_down(name):
def health_check():
"""One health pass. Returns the health dict. Fix actions are
rate-limited by HEALTH_FIX_COOLDOWN."""
rate-limited by HEALTH_FIX_COOLDOWN.
The stock SSID-pool broadcast segfaults pineapd on this firmware; when
pineapd is unreachable the pool broadcast is disabled before restarting,
since it is the only known crash cause."""
h = _health
rc, out, err = device_run([HAK5CMD, 'PING'], timeout=10)
h['pineap_up'] = rc == 0 and 'PONG' in (out or '')
@@ -3214,20 +3218,18 @@ def health_check():
now = time.time()
if now - h['last_fix'] < HEALTH_FIX_COOLDOWN:
return dict(h)
count = _sigsegv_count()
if h['sigsegv_last'] is not None and count > h['sigsegv_last']:
# Crash-loop signature: disable the SSID pool broadcast and restart.
pool = _uci_section('pineapd.@ssidpool[0]')
if pool.get('disable') != '1':
device_run(['uci', 'set', 'pineapd.@ssidpool[0].disable=1'])
device_run(['uci', 'commit', 'pineapd'])
device_run(['/etc/init.d/pineapd', 'restart'], timeout=30)
h['last_action'] = 'pool-disabled + pineapd restart (SIGSEGV crash-loop)'
h['last_action'] = 'SSID pool broadcast disabled (pineapd crash-loop fix)'
elif _monitor_down('wlan1mon'):
device_run(['ip', 'link', 'set', 'wlan1mon', 'up'], timeout=10)
h['last_action'] = 'wlan1mon brought up'
else:
device_run(['/etc/init.d/pineapd', 'restart'], timeout=30)
h['last_action'] = 'pineapd restart'
h['sigsegv_last'] = count
device_run(['/etc/init.d/pineapd', 'restart'], timeout=30)
h['sigsegv_last'] = _sigsegv_count()
h['last_fix'] = now
h['fixes'] += 1
return dict(h)