gpsd: add wrapper script for hotplug/respawn handling

Gpsd needs some time to create its Unix socket after the process starts.
The hotplug call in service_started() is triggered too early, before the
socket is ready, causing failures in scripts that depend on it.

Additionally, when gpsd crashes and procd respawns it, service_started() is
not called again, so no hotplug event is emitted on respawn. Therefore scripts
listening for gpsd availability miss the STARTED event.

This commit ensures the hotplug call waits for the socket to appear,
so dependent scripts reliably see the STARTED event, even after respawns.

Signed-off-by: Oliver Sedlbauer <os@dev.tdt.de>
This commit is contained in:
Oliver Sedlbauer
2026-01-28 16:57:06 +01:00
committed by Florian Eckert
parent 292214e76a
commit 4faa112269
3 changed files with 51 additions and 12 deletions

View File

@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=gpsd PKG_NAME:=gpsd
PKG_VERSION:=3.26.1 PKG_VERSION:=3.26.1
PKG_RELEASE:=1 PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@SAVANNAH/$(PKG_NAME) PKG_SOURCE_URL:=@SAVANNAH/$(PKG_NAME)
@@ -141,6 +141,7 @@ define Package/gpsd/install
$(INSTALL_BIN) ./files/gpsd.init $(1)/etc/init.d/gpsd $(INSTALL_BIN) ./files/gpsd.init $(1)/etc/init.d/gpsd
$(INSTALL_DIR) $(1)/usr/sbin $(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/gpsd $(1)/usr/sbin/ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/gpsd $(1)/usr/sbin/
$(INSTALL_BIN) ./files/usr/sbin/gpsd-wrapper $(1)/usr/sbin/
$(INSTALL_DIR) $(1)/etc/gpsd $(INSTALL_DIR) $(1)/etc/gpsd
$(INSTALL_BIN) ./files/etc/gpsd/device-hook $(1)/etc/gpsd/ $(INSTALL_BIN) ./files/etc/gpsd/device-hook $(1)/etc/gpsd/

View File

@@ -3,8 +3,9 @@
START=50 START=50
USE_PROCD=1 USE_PROCD=1
PROG=/usr/sbin/gpsd PROG=/usr/sbin/gpsd-wrapper
NAME=gpsd NAME=gpsd
SOCKET=/var/run/gpsd.sock
LOG_LEVEL="0" LOG_LEVEL="0"
@@ -36,7 +37,7 @@ gpsd_instance()
procd_append_param command -S "$port" procd_append_param command -S "$port"
procd_append_param command -D "$LOG_LEVEL" procd_append_param command -D "$LOG_LEVEL"
[ "$readonly" = "1" ] && procd_append_param command -b [ "$readonly" = "1" ] && procd_append_param command -b
procd_append_param command -F /var/run/gpsd.sock procd_append_param command -F "$SOCKET"
for device in $devices; do for device in $devices; do
procd_append_param command "$device" procd_append_param command "$device"
done done
@@ -55,12 +56,3 @@ service_triggers() {
procd_add_reload_trigger "$NAME" procd_add_reload_trigger "$NAME"
procd_add_validation validate_section_gpsd procd_add_validation validate_section_gpsd
} }
service_started() {
local enabled
enabled="$(uci_get gpsd core enabled 0)"
[ "$enabled" = "0" ] && return
env -i ACTION="STARTED" /sbin/hotplug-call gpsd
}

View File

@@ -0,0 +1,46 @@
#!/bin/sh
SOCKET="/var/run/gpsd.sock"
trap_with_arg() {
func="$1" ; shift
for sig; do
# shellcheck disable=SC2064
trap "$func $sig" "$sig"
done
}
func_trap() {
logger -t "gpsd-wrapper[$$]" "Sending signal ${1}..."
kill "-${1}" "$CHILD" 2>/dev/null
}
wait_for_socket_and_hotplug() {
local count=0
while [ $count -lt 15 ]; do
[ -S "$SOCKET" ] && break
sleep 1
count=$((count + 1))
done
if [ -S "$SOCKET" ]; then
logger -t "gpsd-wrapper[$$]" "Socket ready, sending hotplug call"
env -i ACTION="STARTED" /sbin/hotplug-call gpsd
else
logger -t "gpsd-wrapper[$$]" \
"Socket $SOCKET not ready after ${count}s, hotplug skipped"
fi
}
main() {
trap_with_arg func_trap INT TERM KILL
/usr/sbin/gpsd "$@" &
CHILD="$!"
wait_for_socket_and_hotplug
wait "$CHILD"
}
main "$@"