fix(freebsd): make the rc.d scripts start their services
Problem
The contrib/freebsd rc.d scripts shipped in v2.2.0 could not start either service. There were three independent blockers, each confirmed by driving the scripts through the official FreeBSD 14.3 rc.subr with command execution intercepted:
-t ${desc}was unquoted.desc="Heliograph hub"became-t Heliographafter rc.subr'seval, andhubbecame daemon(8)'s child program.${name}_flagsis rc.subr's reservedrc_flags, which is inserted between$commandand$command_args. The hub's defaultsmoked_flags=-downsampletherefore went to/usr/sbin/daemonitself (illegal option -- d).${name}_user=smokemakes rc.subr wrap the start insu -m smoke, so daemon(8) ran assmokeand could not create/var/run/<name>.pid, while the script also passed-u smoke.
There was also a fourth bug: : ${smoke_agent_spool:="…"} replaces an empty value too, so the documented smoke_agent_spool="" never disabled the spool.
The existing CI only ran sh -n, which cannot catch any of these.
Fix
This follows the ports convention used by sysutils/node_exporter and net-mgmt/prometheus2:
- rc.subr's standard
${name}_userruns daemon(8) and the child unprivileged; there is no-u. - The supervisor pidfile (
-P) lives in/var/run/<name>/, owned by the service user and created instart_precmd. The supervisor can create it and remove it on exit, andservice stopsignals the supervisor rather than the child, which-rwould otherwise restart. - The process title and the syslog tag (
-t/-T) are the single word${name}. The defaultprocname(/usr/sbin/daemon) matches thedaemon: <name>[pid]title for status/stop. - Extra flags move to
${name}_args. A leftover${name}_flagsvalue from v2.2.0 is migrated to_argswith a warning, so it no longer reaches daemon(8). smoke_agent_spool=""andsmoked_args=""now take effect: they use=rather than:=.- Unchanged: the DSN is passed via the
SMOKED_DSNenvironment variable, never argv; the agent always gets an explicit-spool-dir=; the spool dir is created in precmd.
Emitted start line, before and after (rc.subr harness):
before: su -m smoke -c 'sh -c " /usr/sbin/daemon -downsample -r -S -P /var/run/smoked.pid -t Heliograph hub -u smoke /usr/local/bin/smoked ..."'
after: su -m smoke -c 'sh -c " /usr/sbin/daemon -r -T smoked -t smoked -P /var/run/smoked/smoked.pid /usr/local/bin/smoked -serve -addr 127.0.0.1:8087 -webdir /usr/local/share/heliograph/web -downsample"'
Real verification in CI
freebsd-test now also runs .github/scripts/freebsd-rc-test.sh inside the FreeBSD VM. It installs the binaries and rc.d scripts as the README describes, creates the smoke user, and checks through service(8):
- smoked:
onestartbrings up/api/targetswith the demo targets, andonestatuspasses. The supervisor and the child both run assmoke, the child's argv is exact, and its output reaches syslog under the tagsmoked. - Restart on crash: killing the child brings back a new one.
- Leftover
smoked_flags:onerestartwith it set gives a new supervisor, the warning, and the flag on smoked. - DSN stays off argv: with a DSN set,
procstat -eshowsSMOKED_DSNin the child's environment andpgrep -ffinds it on no command line. - smoked stop: after
onestop,onestatusfails, no process is left, and the pidfile is gone. - smoke_agent: with a throwaway cert and an unreachable hub, the supervisor and child run as
smoke,spool.lockis owned bysmoke, argv and the syslog tag are right,smoke_agent_spool=""yields-spool-dir=, andonestopcleans up.