collector: survive bluetoothd hangs and restarts

- every BlueZ call runs off the asyncio thread with a timeout; if bluetoothd
  stays unresponsive for 30 s the collector restarts bluetooth.service and
  exits for a clean re-registration
- Type=notify + WatchdogSec for buttontask-collector, never give up restarting
- bluetooth.service drop-in: Restart=always (BlueZ 5.55 crashes on assert/SEGV),
  installed by device-install.sh and OTA (bt-update)
- bt-service: bluez-restart action for the collector

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-10 07:10:02 +00:00
co-authored by Claude Opus 5.5
parent 588c2e0135
commit 115879ab67
10 changed files with 265 additions and 89 deletions
@@ -0,0 +1,10 @@
# Installed as /etc/systemd/system/bluetooth.service.d/override.conf
# bluetoothd 5.55 on this board crashes now and then (GLib assert / SEGV).
# Stock unit has no Restart=, so after a crash BLE stayed dead until something
# happened to D-Bus-activate it again.
[Unit]
StartLimitIntervalSec=0
[Service]
Restart=always
RestartSec=2
+10 -2
View File
@@ -2,9 +2,17 @@
Description=ButtonTask BLE Sensor Collector
After=bluetooth.service dbus.service
Wants=bluetooth.service
# Never give up restarting: the collector exits on purpose whenever
# bluetoothd restarts or hangs, to re-register GATT/advertising from scratch.
StartLimitIntervalSec=0
[Service]
Type=simple
# Type=notify + watchdog: the collector sends READY=1 after GATT start and
# WATCHDOG=1 every loop tick; a stuck event loop gets killed and restarted.
Type=notify
NotifyAccess=main
WatchdogSec=60
TimeoutStartSec=90
User=buttontask
Group=buttontask
SupplementaryGroups=bluetooth
@@ -12,7 +20,7 @@ WorkingDirectory=/opt/buttontask/current/collector
Environment=BUTTONTASK_ROOT=/opt/buttontask
Environment=PYTHONUNBUFFERED=1
ExecStart=/usr/bin/python3 /opt/buttontask/current/collector/main.py
Restart=on-failure
Restart=always
RestartSec=3
[Install]
+5 -1
View File
@@ -48,6 +48,10 @@ run_action() {
collector-off)
systemctl disable --now buttontask-collector
;;
bluez-restart)
# Called by the collector when bluetoothd stops answering D-Bus.
systemctl restart bluetooth
;;
units)
systemctl list-units --type=service --all --no-legend --plain --no-pager \
|| systemctl list-units --type=service --all --no-legend --no-pager
@@ -60,7 +64,7 @@ run_action() {
emit_journal
;;
*)
echo "usage: bt-service {start|stop|restart|collector-on|collector-off|units|journal}" >&2
echo "usage: bt-service {start|stop|restart|collector-on|collector-off|bluez-restart|units|journal}" >&2
exit 2
;;
esac
+7
View File
@@ -210,6 +210,13 @@ cmd_stage() {
fi
log "synced buttontask-collector.service"
fi
if [ -f "$dest/webconfig/bluetooth.service.d/override.conf" ]; then
install -d /etc/systemd/system/bluetooth.service.d
sed 's/\r$//' "$dest/webconfig/bluetooth.service.d/override.conf" \
> /etc/systemd/system/bluetooth.service.d/override.conf
systemctl daemon-reload 2>/dev/null || true
log "synced bluetooth.service.d/override.conf"
fi
write_status switching "$ver"
switch_to "$dest"