Skip to content

fix: msposd OSD lost on Star6E boot (missing -d, waybeam respawn race) - #2395

Open
moro161 wants to merge 1 commit into
OpenIPC:masterfrom
moro161:fix-vtx-osd-loss
Open

fix: msposd OSD lost on Star6E boot (missing -d, waybeam respawn race)#2395
moro161 wants to merge 1 commit into
OpenIPC:masterfrom
moro161:fix-vtx-osd-loss

Conversation

@moro161

@moro161 moro161 commented Sep 11, 2026

Copy link
Copy Markdown

Summary

Two related bugs found tracking down VTX-side OSD loss on a
ssc338q_fpv_openipc-urllc-aio-nor (RunCam WiFiLink) nightly build,
both in start_telemetry():

  • OSD never appears at all: the msposd invocation is missing
    -d/--osd. Without it, msposd runs and correctly parses FC
    telemetry (confirmed with -v: detects the FC fine) but never calls
    MI_RGN_Init / draws anything.

  • OSD appears at boot, then vanishes for good after a few seconds
    (Star6E SoCs, e.g. RunCam WiFiLink): waybeam does an internal
    cold-restart shortly after its own startup (fork+exec, to lock in a
    cold-boot FPS re-kick — see src/star6e_pipeline.c in
    OpenIPC/waybeam), which
    destroys and recreates its venc channel. msposd binds its OSD
    region to whatever venc channel exists at its own startup, once, via
    MI_RGN_Init, and never reattaches. This script always starts
    msposd right after S95waybeam returns, which is before
    waybeam's internal respawn fires — so the OSD region is always
    orphaned when the channel gets torn down, even with -d fixed.

Fix

  • Add -d to the msposd invocation.
  • Add a background watcher (watch_waybeam_respawn) that detects the
    waybeam respawn via /tmp/waybeam.log content (re-scanning the whole
    file each check, since the respawn can complete before the watcher
    starts — not a fixed delay) and, once the respawned channel is
    actually up (a second "ISP channel ready" line, not a guessed
    sleep), restarts msposd so it reattaches. Bounded loops are a
    safety net, not the wait mechanism.
  • No-op on SoCs/builds where waybeam doesn't do this respawn, or
    majestic is in use instead — the log marker never appears and the
    watcher just exits after its timeout.

Test plan

  • Verified root cause with msposd -v in foreground: no
    MI_RGN_Init/region activity without -d; with -d, region
    created successfully and live telemetry flows.
  • Verified the channel-teardown race directly via logread:
    client [X] disconnected, module:vencMI_VENC_IMPL_DestroyChn
    client [Y] connected, module:venc, correlated with
    waybeam's own "Reinit requested: cold restart via fork+exec" /
    "Respawning:" log lines.
  • Verified the fix end-to-end across three clean on-device reboots
    with no manual intervention: watcher log line
    ("waybeam respawned post-boot, restarting msposd to reattach OSD") appears, grep -c "ISP channel ready" /tmp/waybeam.log
    reads 2 at that point (real signal, not a timing guess), msposd
    comes back up with -d, stable PID over 30+s of polling
    afterward on each reboot.
  • Not tested on non-Star6E SoCs / majestic-based images (no such
    hardware on hand) — the watcher is designed to be a no-op there,
    but that's unverified.

msposd's start_telemetry() invocation was missing -d/--osd, so it never
called MI_RGN_Init and drew nothing even though it ran fine and parsed
FC telemetry correctly.

Separately, on Star6E SoCs (e.g. RunCam WiFiLink/ssc338q) waybeam does
an internal cold-restart shortly after its own startup to lock in a
cold-boot FPS re-kick, which destroys and recreates its venc channel.
msposd binds its OSD region to whatever channel exists at its own
startup, once, and this script always starts msposd before that
respawn fires -- so the OSD region was silently destroyed with the old
channel and never came back, even with -d. Symptom: OSD shows for a
few seconds after boot, then vanishes for good.

Added a background watcher that detects the waybeam respawn (by
content, not a fixed delay, since the respawn can complete before we
start watching) and restarts msposd once the respawned channel is
actually up. No-op on SoCs/builds where waybeam doesn't do this
respawn, or majestic is in use instead.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Restore msposd OSD after waybeam boot respawn

🐞 Bug fix 🕐 10-20 Minutes

Grey Divider

AI Description

• Enables msposd rendering by passing the required -d flag.
• Detects waybeam’s post-boot respawn and restarts msposd after encoder readiness.
• Uses bounded polling to remain harmless on unaffected SoCs and majestic builds.
Diagram

graph TD
  A["Telemetry startup"] --> B["msposd with OSD"] --> C{"Respawn logged?"}
  C -- "No" --> D["Watcher exits"]
  C -- "Yes" --> E{"Channel ready?"} --> F["Restart msposd"] --> G["OSD reattached"]
  E -- "Timeout" --> F
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Teach msposd to reattach dynamically
  • ➕ Handles any encoder-channel recreation without platform-specific startup scripts
  • ➕ Eliminates log polling and forced process restarts
  • ➖ Requires upstream msposd changes and a new package release
  • ➖ Broadens the scope beyond this targeted boot regression
2. Expose explicit waybeam readiness signaling
  • ➕ Provides a stable synchronization contract instead of parsing log text
  • ➕ Could coordinate all encoder-dependent services
  • ➖ Requires coordinated waybeam and init-script changes
  • ➖ Deferring initial startup may not cover later channel recreation

Recommendation: The background watcher is the best targeted fix for the current image because it uses observed lifecycle signals, handles already-completed respawns, and safely times out elsewhere. Dynamic reattachment in msposd would be the stronger long-term solution if upstream changes are feasible.

Files changed (1) +53 / -1

Bug fix (1) +53 / -1
wifibroadcastEnable OSD rendering and recover from waybeam respawns +53/-1

Enable OSD rendering and recover from waybeam respawns

• Adds the required '-d' option to msposd launches. Introduces a bounded background watcher that detects waybeam’s cold respawn and encoder readiness through '/tmp/waybeam.log', then restarts msposd to bind its overlay to the recreated channel.

general/package/wifibroadcast-ng/files/wifibroadcast

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (1) 📜 Skill insights (0)

Grey Divider


Action required

1. Some camera targets remain untested 📘 Rule violation ☼ Reliability
Description
watch_waybeam_respawn is added to the shipped telemetry startup path, but the PR test plan leaves
the non-Star6E and majestic hardware item unchecked and explicitly says it was not tested. The added
watcher is intended to execute or no-op across those builds, so those camera paths remain within the
claimed blast radius without board output confirming either behavior.
Code

general/package/wifibroadcast-ng/files/wifibroadcast[134]

+		[ "$router" = "msposd" ] && watch_waybeam_respawn "$osd_fps" "$serial" "$port_tx" "$size"
Evidence
PR Compliance ID 1 requires every checkbox under a test or verification heading to be checked for
firmware-behavior changes. The cited addition activates the new watcher from the shipped startup
path, while the supplied test plan contains an unchecked item and states that non-Star6E SoCs and
majestic-based images were not tested.

Rule 1: Hardware evidence is present and honest
general/package/wifibroadcast-ng/files/wifibroadcast[134-134]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The shipped telemetry startup behavior changes across camera builds, while the PR explicitly leaves non-Star6E and majestic hardware verification incomplete.

## Fix Focus Areas
- general/package/wifibroadcast-ng/files/wifibroadcast[134-188]

## Recommended Fix
Run the applicable non-Star6E and majestic no-op checks on real cameras, record observable startup, streaming, process, and log results in the PR description, and check the remaining test-plan item.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Slow encoder restarts lose the overlay 🐞 Bug ≡ Correctness
Description
watch_waybeam_respawn falls through to the restart path when its readiness loop times out, without
confirming that a second ISP channel ready marker exists. If replacement-channel initialization
takes longer than six seconds or fails, msposd starts before a usable channel exists and cannot
perform the intended reattachment.
Code

general/package/wifibroadcast-ng/files/wifibroadcast[R181-182]

+		echo_log "waybeam respawned post-boot, restarting msposd to reattach OSD"
+		killall -q msposd
Evidence
The code defines two readiness markers as the signal that the recreated channel is available, but
the bounded loop has no success flag or post-loop guard and execution always reaches the restart.

general/package/wifibroadcast-ng/files/wifibroadcast[154-160]
general/package/wifibroadcast-ng/files/wifibroadcast[174-187]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The readiness loop can time out without finding the second `ISP channel ready` marker, but the code still restarts `msposd` as though the replacement encoder channel were available.

## Fix Focus Areas
- general/package/wifibroadcast-ng/files/wifibroadcast[174-187]

## Recommended Fix
After the bounded loop, explicitly verify that the log contains at least two readiness markers. Restart `msposd` only when that condition is true; otherwise log the timeout and exit the watcher without claiming a successful respawn.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Stopped telemetry can start itself again 🐞 Bug ☼ Reliability
Description
watch_waybeam_respawn backgrounds an untracked subshell, while stop() kills only named telemetry
binaries and never cancels that watcher. A stop or rapid restart during either wait leaves the prior
watcher alive, so it can later kill the new instance or launch msposd after the service was
stopped.
Code

general/package/wifibroadcast-ng/files/wifibroadcast[188]

+	) &
Evidence
The watcher remains alive independently because the subshell is backgrounded, whereas the service
stop path only targets wfb_rx, wfb_tx, wfb_tun, msposd, and mavfwd; the surviving watcher
later executes a global kill and starts a fresh process.

general/package/wifibroadcast-ng/files/wifibroadcast[163-188]
general/package/wifibroadcast-ng/files/wifibroadcast[255-279]
general/package/wifibroadcast-ng/files/S98wifibroadcast[3-12]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The detached waybeam watcher is not owned by the service lifecycle, allowing it to survive a stop or overlap a later service generation.

## Fix Focus Areas
- general/package/wifibroadcast-ng/files/wifibroadcast[163-188]
- general/package/wifibroadcast-ng/files/wifibroadcast[255-279]

## Recommended Fix
Record the background watcher's PID when it is launched, cancel and wait for that PID before stopping or starting telemetry, and remove the PID record when the watcher exits. Ensure only the current service generation is allowed to restart `msposd`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: ⚖️ Balanced: This modifies shared firmware startup logic with process supervision, timing, log parsing, and cross-SoC behavior, creating meaningful boot and OSD regression risk despite a single localized edit site.

Grey Divider

Tip of the day
💡 Did you know, you can switch off images and animations for a plain-text comment

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

-o 127.0.0.1:"$port_tx" -z "$size" > /dev/null &
-o 127.0.0.1:"$port_tx" -z "$size" -d > /dev/null &

[ "$router" = "msposd" ] && watch_waybeam_respawn "$osd_fps" "$serial" "$port_tx" "$size"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Some camera targets remain untested 📘 Rule violation ☼ Reliability

watch_waybeam_respawn is added to the shipped telemetry startup path, but the PR test plan leaves
the non-Star6E and majestic hardware item unchecked and explicitly says it was not tested. The added
watcher is intended to execute or no-op across those builds, so those camera paths remain within the
claimed blast radius without board output confirming either behavior.
Agent Prompt
## Issue description
The shipped telemetry startup behavior changes across camera builds, while the PR explicitly leaves non-Star6E and majestic hardware verification incomplete.

## Fix Focus Areas
- general/package/wifibroadcast-ng/files/wifibroadcast[134-188]

## Recommended Fix
Run the applicable non-Star6E and majestic no-op checks on real cameras, record observable startup, streaming, process, and log results in the PR description, and check the remaining test-plan item.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +181 to +182
echo_log "waybeam respawned post-boot, restarting msposd to reattach OSD"
killall -q msposd

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Slow encoder restarts lose the overlay 🐞 Bug ≡ Correctness

watch_waybeam_respawn falls through to the restart path when its readiness loop times out, without
confirming that a second ISP channel ready marker exists. If replacement-channel initialization
takes longer than six seconds or fails, msposd starts before a usable channel exists and cannot
perform the intended reattachment.
Agent Prompt
## Issue description
The readiness loop can time out without finding the second `ISP channel ready` marker, but the code still restarts `msposd` as though the replacement encoder channel were available.

## Fix Focus Areas
- general/package/wifibroadcast-ng/files/wifibroadcast[174-187]

## Recommended Fix
After the bounded loop, explicitly verify that the log contains at least two readiness markers. Restart `msposd` only when that condition is true; otherwise log the timeout and exit the watcher without claiming a successful respawn.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

done
msposd -b 115200 -c 8 -r "$osd_fps" -m /dev/"$serial" \
-o 127.0.0.1:"$port_tx" -z "$size" -d > /dev/null &
) &

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Stopped telemetry can start itself again 🐞 Bug ☼ Reliability

watch_waybeam_respawn backgrounds an untracked subshell, while stop() kills only named telemetry
binaries and never cancels that watcher. A stop or rapid restart during either wait leaves the prior
watcher alive, so it can later kill the new instance or launch msposd after the service was
stopped.
Agent Prompt
## Issue description
The detached waybeam watcher is not owned by the service lifecycle, allowing it to survive a stop or overlap a later service generation.

## Fix Focus Areas
- general/package/wifibroadcast-ng/files/wifibroadcast[163-188]
- general/package/wifibroadcast-ng/files/wifibroadcast[255-279]

## Recommended Fix
Record the background watcher's PID when it is launched, cancel and wait for that PID before stopping or starting telemetry, and remove the PID record when the watcher exits. Ensure only the current service generation is allowed to restart `msposd`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@openipc-ai openipc-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the detailed write-up — the -d half is a real bug with a real fix, and the msposd -v evidence for it is exactly the right kind. The watcher half has a blocking problem, though: it keys on a package that no board in either repository builds.

Blocking — waybeam is selected by no defconfig, here or in builder

watch_waybeam_respawn depends entirely on /tmp/waybeam.log existing, which requires waybeam to be installed. It never is:

  • general/package/waybeam/Config.in carries depends on !BR2_PACKAGE_MAJESTIC — the two drive the same sensor and encoder, and sigmastar-osdrv-infinity6e installs the MI libraries only when Majestic is off.
  • Every defconfig in OpenIPC/builder that sets BR2_PACKAGE_WIFIBROADCAST_NG=y — all nine of them, ssc338q_fpv, ssc338q_fpv_runcam-wifilink, ssc338q_fpv_openipc-urllc-aio, ssc338q_fpv_openipc-mario-aio, ssc338q_fpv_openipc-thinker-aio, ssc338q_fpv_caddx-fly, ssc338q_fpv_emax-wyvern-link, ssc30kq_fpv, ssc377qe_fpv_ccdcam-im50q01-tipoman — also sets BR2_PACKAGE_MAJESTIC=y. So waybeam is excluded by construction on precisely the boards that ship this script.
  • grep -rl BR2_PACKAGE_WAYBEAM=y across both trees returns nothing.

On every image built from these repositories the streamer is majestic, the marker never appears, and the watcher spends ~15 s after each boot grepping a file that does not exist before giving up. That is best_practices.md §6.1 — code no defconfig can reach.

If you were misled by the NOT_BUILT comment in .github/scripts/ci-matrix.py ("It is selected by the FPV variants in OpenIPC/builder"), that sentence is stale and I will fix it separately.

This also means the test-plan evidence cannot have come from a stock nightly of ssc338q_fpv_openipc-urllc-aio-norgrep -c "ISP channel ready" /tmp/waybeam.log reading 2 requires a waybeam image, and that board builds majestic. Could you say how the image under test was built? If you are carrying a local waybeam-enabled variant, the watcher belongs wherever that variant lives, not in the shared script.

The good news

The -d bug is real and it is on the configuration everyone actually runs. Split that out with the $size guard described inline and it is a small, shippable PR. See the inline comments for why -z alone was supposed to cover this and what actually goes wrong.

If the reattach problem is real beyond waybeam — and it plausibly is, since msposd binds its region once and majestic restarts on config changes too — the durable fix is in msposd: reattach on channel loss, rather than have a shell script scrape a log and kill a process. A watcher in general/package/ reaches every FPV camera and can only ever cover the one restart path it was written for.

Process notes

  • Commit subject is fix: msposd OSD lost on Star6E boot (...). House style is area: lowercase imperative summary, e.g. wifibroadcast: pass -d so msposd actually draws the OSD.
  • CI here builds all 99 boards for this path but covers none of the FPV consumers — ci-matrix.py --stdin reports "reaches no board of its own" — so hardware evidence is the only gate this change has.
  • Local checks do pass on the branch: test_shell_parse.sh, test_strip_shell_comments.sh and ci-matrix.py --self-test are all clean.

Two of the inline findings below were also raised by the automated review and I agree with both.

Comment on lines 129 to +132
size=$(curl -s localhost/api/v1/config.json | jsonfilter -qe "@.video0.size")
fi
msposd -b 115200 -c 8 -r "$osd_fps" -m /dev/"$serial" \
-o 127.0.0.1:"$port_tx" -z "$size" > /dev/null &
-o 127.0.0.1:"$port_tx" -z "$size" -d > /dev/null &

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-d is correct and I want to keep it — but it is not the whole story, and the PR description has the cause slightly wrong.

DrawOSD starts false in msposd and is set from two places in the option loop: case 'd', and case 'z' — but case 'z' sets it only inside if (limit), where limit = strchr(buffer, 'x'). So -z 1920x1080 already implies -d. The only way the existing line draws nothing is $size arriving empty or without an x, which happens when majestic's HTTP server is not yet listening at S98 time, or .video0.size is unset in majestic.yaml.

That matters because -d alone masks it rather than fixing it: with an empty -z, set_resolution() is never called and msposd falls back to its built-in default, clamped to 1280x720. The overlay then comes up at the wrong geometry instead of not at all — which is harder to notice than the current failure.

Please guard the value as well, something like:

size=$(curl -s localhost/api/v1/config.json | jsonfilter -qe "@.video0.size")
case "$size" in
	*x*) ;;
	*) size=1920x1080; echo_log "video0.size unavailable, OSD falling back to $size" ;;
esac

Keep -d as the belt-and-braces so the overlay no longer depends on that curl succeeding.

-o 127.0.0.1:"$port_tx" -z "$size" > /dev/null &
-o 127.0.0.1:"$port_tx" -z "$size" -d > /dev/null &

[ "$router" = "msposd" ] && watch_waybeam_respawn "$osd_fps" "$serial" "$port_tx" "$size"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the blocking line. waybeam is built by no defconfig in this repository or in OpenIPC/builder — its Config.in has depends on !BR2_PACKAGE_MAJESTIC, and every builder defconfig that selects BR2_PACKAGE_WIFIBROADCAST_NG also sets BR2_PACKAGE_MAJESTIC=y.

So on every image that ships this script, /tmp/waybeam.log does not exist and the watcher is unreachable code that costs ~15 s of background polling after each boot. Details and the full defconfig list are in the review body.

Comment on lines +145 to +147
# waybeam (the venc/encoder daemon on Star6E SoCs) does an internal
# cold-restart shortly after its own startup (fork+exec, to lock in a
# cold-boot FPS re-kick — see src/star6e_pipeline.c in OpenIPC/waybeam),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mechanism is not what waybeam does, and the comment will outlive the misunderstanding if it lands.

star6e_pipeline_cold_boot_fps_rekick() in src/star6e_pipeline.c is a plain MI_SNR_SetFps re-issued from the run loop about 1.5 s after start. It does not restart the process, and it does not touch the venc channel.

The fork+exec cold restart lives in src/venc_respawn.c and is reached only from venc_api_request_reinit(), whose callers are SIGHUP, /api/v1/restart, /api/v1/defaults, and a RESTART-class /api/v1/set. There is no automatic self-restart shortly after boot for this script to race with.

So whatever produced the teardown you captured in logread had some other trigger, and it is worth identifying before building a workaround around it — the timing assumption this watcher encodes ("msposd always starts before the respawn fires") may not hold for the real trigger.

# respawn (or majestic is in use instead) — /tmp/waybeam.log never gets
# the marker and this just exits after the timeout.
watch_waybeam_respawn() {
osd_fps="$1"; serial="$2"; port_tx="$3"; size="$4"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These assignments are not local, so they write the caller's variables. It happens to be harmless here only because start_telemetry() uses the same four names with the same values — a rename on either side turns it into a silent bug.

local is available in the busybox ash built here (general/overlay/usr/sbin/sysupgrade uses it throughout), so:

watch_waybeam_respawn() {
	local osd_fps="$1" serial="$2" port_tx="$3" size="$4"

Comment on lines +166 to +171
elapsed=0
while [ "$elapsed" -lt 30 ]; do
grep -q "Respawning:" /tmp/waybeam.log 2>/dev/null && break
sleep 0.5
elapsed=$((elapsed + 1))
done

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

elapsed counts iterations, not seconds. With sleep 0.5 the bound is 15 s, not 30; the second loop's -lt 20 with sleep 0.3 is 6 s, not 20. The surrounding prose ("just exits after the timeout") reads as though those numbers were seconds.

Either name it tries, or keep seconds and derive the bound — whichever, make the comment state the real wall-clock budget, since that is the number a reviewer needs to weigh against how long the encoder actually takes to come back.

Comment on lines +174 to +182
elapsed=0
while [ "$elapsed" -lt 20 ]; do
[ "$(grep -c "ISP channel ready" /tmp/waybeam.log 2>/dev/null)" -ge 2 ] && break
sleep 0.3
elapsed=$((elapsed + 1))
done

echo_log "waybeam respawned post-boot, restarting msposd to reattach OSD"
killall -q msposd

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the readiness loop times out, execution falls straight through to the restart anyway — there is no success flag and no post-loop guard. So when the replacement channel is slow or never arrives, msposd is killed and restarted against a channel that is not up, re-orphaning the region with no further retry. That is strictly worse than leaving the running instance alone: you lose whatever OSD was there.

Gate the restart on the condition actually being met:

ready=0
tries=0
while [ "$tries" -lt 20 ]; do
	[ "$(grep -c "ISP channel ready" /tmp/waybeam.log 2>/dev/null)" -ge 2 ] && { ready=1; break; }
	sleep 0.3
	tries=$((tries + 1))
done
[ "$ready" = 1 ] || { echo_log "waybeam respawned but the channel never came up, leaving msposd alone"; exit 0; }

(Also raised by the automated review — agreed.)

Comment on lines +183 to +185
while pidof msposd >/dev/null 2>&1; do
sleep 0.2
done

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wait is unbounded and never escalates. killall -q sends SIGTERM; if msposd is wedged, or if a second watcher starts a fresh msposd while this one is waiting, pidof never clears and this subshell spins on a 0.2 s sleep forever — on a flight camera, with no way to notice.

general/package/waybeam/files/S95waybeam in this same tree already solves exactly this, and its stop() is the pattern to copy: a bounded wait_exit(), then killall -9, then report the failure rather than pretend the stop happened. Please bound this the same way and give up loudly if msposd survives SIGKILL.

Comment on lines +186 to +187
msposd -b 115200 -c 8 -r "$osd_fps" -m /dev/"$serial" \
-o 127.0.0.1:"$port_tx" -z "$size" -d > /dev/null &

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a byte-for-byte copy of the invocation at lines 131-132. Two copies of a command line with seven flags will drift — the -d this PR adds is itself an illustration of how easy it is for one of them to be wrong for a long time.

Factor it out:

start_msposd() {
	msposd -b 115200 -c 8 -r "$osd_fps" -m /dev/"$serial" \
		-o 127.0.0.1:"$port_tx" -z "$size" -d > /dev/null &
}

and call it from both places.

done
msposd -b 115200 -c 8 -r "$osd_fps" -m /dev/"$serial" \
-o 127.0.0.1:"$port_tx" -z "$size" -d > /dev/null &
) &

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The subshell is backgrounded and untracked, and stop() kills only wfb_rx wfb_tx wfb_tun msposd mavfwd. So a watcher armed by a previous start outlives a stop, and there is no handle to cancel it.

Two reachable consequences:

  • wifibroadcast stop inside the watcher's ~21 s window kills msposd, then the watcher brings it back up afterwards — the service is nominally stopped with msposd running.
  • wifibroadcast start run twice leaves two watchers. They race each other's killall, and the older one's unbounded pidof wait (line 183) can latch onto the msposd the newer one just started and never return.

If the watcher survives review at all it needs to be tracked — write its PID to /tmp and have stop() kill it, or have it re-check on each iteration that the msposd it was armed for is still the current one.

(Also raised by the automated review — agreed.)

openipc-ai added a commit that referenced this pull request Sep 11, 2026
Two entries in NOT_BUILT carry a prose reason naming who selects the
package downstream, and both had gone stale. A reason nobody can check
is worse than none: it is read as evidence.

waybeam's said "It is selected by the FPV variants in OpenIPC/builder".
It never was. waybeam depends on !BR2_PACKAGE_MAJESTIC, and every
builder defconfig that selects wifibroadcast-ng sets
BR2_PACKAGE_MAJESTIC=y, so the same exclusion that keeps it off this
matrix keeps it off every downstream image too -- no defconfig in
either tree sets BR2_PACKAGE_WAYBEAM=y. That line sent the author of
#2395 chasing an FPV OSD fault through /tmp/waybeam.log, a file no
shipped image writes.

jsonfilter's cited "~97 builder devices". builder#128 removed it from
the 95 that did not need it; what actually holds it in the tree now is
wifibroadcast-ng's select and builder's apfpv devices.

Comment only -- no selector, board or package list changes, and
--self-test still reports 99 boards / 135 packages / 56 cases.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants