Skip to content

[RM2 3/3] Add crash-safe panel supervision - #4

Open
jimmystridh wants to merge 6 commits into
MaximeRivest:mainfrom
jimmystridh:pr/rm2-panel-supervisor
Open

jimmystridh wants to merge 6 commits into
MaximeRivest:mainfrom
jimmystridh:pr/rm2-panel-supervisor

Conversation

@jimmystridh

Copy link
Copy Markdown

What changed

  • replace shell-owned display lifecycle state with a standalone native panel supervisor
  • atomically persist typed takeover phases and publish the app process group before exec
  • preserve xochitl's original state, supervise descendants, and bound TERM-to-KILL cleanup
  • add an explicit fail-closed recovery command for stale ownership after uncatchable termination
  • run the device acceptance suite inside the same supervised panel session and propagate probe failures
  • document deployment and the verified RM2 device results

Why

Stopping xochitl and transferring the panel spans service state, vendor lock files, signals, process groups, and crash recovery. The earlier shell implementation accumulated too many ambiguous transition windows. A native supervisor provides one typed, durable lifecycle boundary while leaving the shell entrypoints as thin launchers.

Impact

takeover.sh and panel-recover.sh now delegate to panel-supervisor. Concurrent and stale takeovers fail closed without signalling unauthenticated process groups or changing display state. The device suite no longer owns a second copy of the privileged lifecycle.

Validation

  • sanitizer-backed supervisor and device-suite tests on macOS and Linux
  • sh/dash wrapper tests and ShellCheck
  • persistent Linux container coverage with a non-reaping PID 1
  • Clang static analysis and strict C11 compilation
  • full RM2 ARMv7 SDK build

Series

This is 3 of 3 and depends on #3, which in turn depends on #2. This draft targets main and therefore temporarily includes the preceding four commits. The focused two-commit delta is jimmystridh/quill#3.

Centralize signal-aware waits, evdev discovery, surface setup, CLI parsing, and pen configuration for device demos. Build the support code as a static archive and migrate the termination probe while keeping RM2 interactive demos gated until their portable conversion.
Move every demo onto the shared runtime and canonical surface APIs, discover live pen ranges, and gate color-only programs by capability. Add a format-safe map renderer with clipped backing-patch restoration and build the archived vanishing-trail example for both supported targets.
Replace shell-owned display lifecycle state with a standalone native supervisor. Persist typed takeover phases atomically, publish the app process group before exec, preserve xochitl's original state, and require explicit fail-closed recovery after uncatchable termination.
Make the acceptance suite re-enter through the native takeover owner, bound child termination, validate both QImage constructor ABIs, and propagate failures. Add end-to-end lifecycle coverage plus deployment and RM2 device documentation.
@jimmystridh
jimmystridh marked this pull request as ready for review August 20, 2026 00:04

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 781c21b71b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

run_status "$SUPERVISOR" recover
assert_eq "$RUN_STATUS" 1 "recovery ignored the live recorded group"
kill -0 "$app" 2>/dev/null || fail "recovery signalled the stale group"
kill -TERM "$app" 2>/dev/null || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Terminate the fixture's entire process group

When the SIGKILL recovery test stops hold-app, signalling only the shell PID can leave its current sleep 1 child alive in the recorded process group. process_stopped then observes only the shell zombie, while the subsequent recovery correctly sees the remaining group member and refuses recovery, causing ./scripts/test-host.sh to fail with “recovery rejected a zombie-only recorded group.” Signal -$app or wait until the complete process group is gone before asserting recovery succeeds.

Useful? React with 👍 / 👎.

Comment thread scripts/device-suite.sh
Comment on lines 187 to +189
echo "=== acceptance probe ==="
./device_acceptance_probe
echo "acceptance_code=$?"
rm -f /tmp/epframebuffer.lock
run_command ./device_acceptance_probe
record_status acceptance $?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Capture probe failures without triggering errexit

When device_acceptance_probe exits nonzero, run_command propagates that status as a simple command while the script has set -e, so the suite exits before record_status, lock cleanup, and all subsequent probes run. This defeats the new aggregate suite_status reporting precisely when an on-device experiment fails; invoke the command in an errexit-safe conditional and record its status explicitly, as is done by the host wrapper.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant