Skip to content

Add cpp_supervised_app_simple example for the Alive API#362

Open
Narasimha2211 wants to merge 1 commit into
eclipse-score:mainfrom
Narasimha2211:234-cpp-supervised-app-simple
Open

Add cpp_supervised_app_simple example for the Alive API#362
Narasimha2211 wants to merge 1 commit into
eclipse-score:mainfrom
Narasimha2211:234-cpp-supervised-app-simple

Conversation

@Narasimha2211

Copy link
Copy Markdown
Contributor

Closes #234

What

Adds examples/cpp_supervised_app_simple, a minimal example of score::mw::lifecycle::Alive: construct Alive, report Running, then call ReportAlive() in a loop until SIGTERM/SIGINT. No deadline/checkpoint supervision — that's what distinguishes it from the existing cpp_supervised_app, which uses the HealthMonitor/DeadlineMonitor API instead.

How

  • main.cpp / BUILD are modeled closely on cpp_supervised_app's structure (signal handling, set_process_name, getopt-based CLI with -s <sleep-ms>), swapping the HealthMonitor block for score::mw::lifecycle::Alive + report_running(). Depends on the //score/launch_manager:alive_cc and :lifecycle_cc aliases — the same public-alias pattern the existing examples already use, since the underlying alive/lifecycle_client targets have restricted visibility. Alive's constructor can throw per its documented contract, so it's wrapped in try/catch for a clean error message instead of an unhandled-exception terminate().
  • Registered as a cpp_supervised_app_simple component in examples/demo_verification/lifecycle_demo_test.json, added to the Running run target's depends_on. Left application_type unset (defaults to "Reporting", same as lifecycle_app) since this app only demonstrates the alive heartbeat, not deadline-checkpoint supervision — happy to switch to Reporting_And_Supervised if that's the preferred classification.
  • Added the binary to demo_verification/BUILD's integration_test binaries list and to test_examples.py's _DEMO_APPS.
  • Documented the app in examples/README.md's table.

A bug I found and fixed along the way

Wiring this into the demo config surfaced a real, pre-existing bug: cpp_supervised_app_simple is a literal prefix-superstring of cpp_supervised_app, and test_examples.py's process matching was a plain unanchored substring grep over /proc/*/cmdline. That means grep -qa 'cpp_supervised_app' would also match cpp_supervised_app_simple's cmdline — breaking _assert_not_running(target, "cpp_supervised_app") right after the existing SIGKILL crash-recovery step (it would spuriously find the still-alive _simple process and report the killed app as still running, false-negating that assertion).

I verified this concretely (not just by inspection) by simulating /proc/*/cmdline-style files locally — NUL-separated argv, both bare-name and full-path forms — and reproducing the false match. Then I fixed _assert_running/_assert_not_running/_send_signal to turn cmdline's NUL-separated argv into one-token-per-line and anchor the match (^binary$ or ^.*/binary$) instead of a raw substring search, and re-ran the same simulation against the fixed logic to confirm it: distinguishes the two names correctly, still matches full-path argv[0], and doesn't self-match the invoking shell's own command line (the anchoring subsumes the original bracket-class self-match-avoidance trick, so I dropped that in favor of the anchor).

Verification note

This repo requires Bazel, which isn't available in my environment, so I could not build or run the integration test end-to-end. What I did verify:

  • Read the actual headers (score/launch_manager/src/alive/src/alive.h, .../lifecycle_client/src/report_running.h) to confirm the API surface, include paths, and target/alias visibility.
  • Modeled the new app closely on the existing, presumably-working cpp_supervised_app example.
  • Empirically simulated the test_examples.py matching-logic bug and fix outside Bazel, as described above.
  • python3 -m json.tool on the modified lifecycle_demo_test.json and ast.parse on test_examples.py — both syntactically valid.

CI should be treated as the real verification here — happy to iterate on anything that doesn't hold up once it actually builds and runs.

…e#234)

Adds a minimal example showcasing score::mw::lifecycle::Alive, as
requested: construct Alive, report Running, then ReportAlive() in a
loop until SIGTERM/SIGINT, with no deadline/checkpoint supervision
(that's what distinguishes it from the existing cpp_supervised_app,
which uses the HealthMonitor/DeadlineMonitor API instead).

- examples/cpp_supervised_app_simple/main.cpp + BUILD: modeled closely
  on cpp_supervised_app's structure (signal handling, set_process_name,
  getopt-based CLI with -s <sleep-ms>), swapping the HealthMonitor
  block for score::mw::lifecycle::Alive + report_running(). Depends on
  the //score/launch_manager:alive_cc and :lifecycle_cc aliases (same
  public-alias pattern the existing examples already use, since the
  underlying alive/lifecycle_client targets have restricted
  visibility). Alive construction can throw per its documented
  contract, so it's wrapped in try/catch for a clean error message
  instead of an unhandled-exception terminate().
- Registered as a new "cpp_supervised_app_simple" component in
  examples/demo_verification/lifecycle_demo_test.json, added to the
  Running run target's depends_on. Left application_type unset
  (defaults to "Reporting", same as lifecycle_app) since this app only
  demonstrates the alive heartbeat, not deadline-checkpoint
  supervision -- happy to change to Reporting_And_Supervised if a
  maintainer prefers that classification.
- Added the new binary to demo_verification/BUILD's integration_test
  binaries list and to test_examples.py's _DEMO_APPS.
- Documented the new app in examples/README.md's app table.

Found and fixed a real bug while wiring up the demo config: this
app's name is a literal prefix-superstring of the existing
"cpp_supervised_app", and test_examples.py's process-matching was a
plain unanchored substring grep over /proc/*/cmdline. That means
grep -qa 'cpp_supervised_app' would also match
"cpp_supervised_app_simple"'s cmdline -- breaking
_assert_not_running(target, "cpp_supervised_app") after the existing
SIGKILL crash-recovery step (it would spuriously find the still-alive
_simple process and report the killed app as still running). Verified
this concretely by simulating /proc/*/cmdline-style files locally
(NUL-separated argv, both bare-name and full-path forms) and
reproducing the false match, then fixing test_examples.py's
_assert_running/_assert_not_running/_send_signal to convert cmdline's
NUL-separated argv into one-token-per-line and anchor the match
(^binary$ or ^.*/binary$) instead of doing a raw substring search --
re-ran the same simulation against the fixed logic and confirmed it
correctly distinguishes the two names, still matches full-path argv0,
and doesn't self-match the invoking shell's own command line (the
anchoring incidentally subsumes the original bracket-class
self-match-avoidance trick, so I dropped it).

Verification note: this repo requires Bazel, which isn't available in
my environment, so I could not build or run the integration test.
Everything above was verified by reading the actual headers
(score/launch_manager/src/alive/src/alive.h,
.../lifecycle_client/src/report_running.h) and BUILD files to confirm
target names, include paths, and visibility, by closely mirroring the
existing cpp_supervised_app example, and by empirically simulating the
test_examples.py matching logic outside Bazel as described above. CI
should be treated as the real verification here.

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

Copy link
Copy Markdown

License Check Results

🚀 The license check job ran with the Bazel command:

bazel run --lockfile_mode=error //:license-check

Status: ⚠️ Needs Review

Click to expand output
[License Check Output]
Extracting Bazel installation...
Starting local Bazel server (8.6.0) and connecting to it...
INFO: Invocation ID: 71339c36-c06f-41f5-8202-2964c2fcce84
Computing main repo mapping: 
Computing main repo mapping: 
Loading: 
Loading: 0 packages loaded
Loading: 0 packages loaded
Loading: 0 packages loaded
    currently loading: 
Loading: 0 packages loaded
    currently loading: 
Loading: 0 packages loaded
    currently loading: 
Analyzing: target //:license-check (1 packages loaded, 0 targets configured)
Analyzing: target //:license-check (1 packages loaded, 0 targets configured)

Analyzing: target //:license-check (37 packages loaded, 10 targets configured)

Analyzing: target //:license-check (85 packages loaded, 10 targets configured)

Analyzing: target //:license-check (86 packages loaded, 10 targets configured)

Analyzing: target //:license-check (144 packages loaded, 2767 targets configured)

Analyzing: target //:license-check (153 packages loaded, 3045 targets configured)

Analyzing: target //:license-check (164 packages loaded, 7267 targets configured)

Analyzing: target //:license-check (164 packages loaded, 8271 targets configured)

Analyzing: target //:license-check (164 packages loaded, 8271 targets configured)

Analyzing: target //:license-check (164 packages loaded, 8271 targets configured)

Analyzing: target //:license-check (168 packages loaded, 10283 targets configured)

Analyzing: target //:license-check (168 packages loaded, 10283 targets configured)

INFO: Analyzed target //:license-check (169 packages loaded, 10409 targets configured).
[12 / 16] JavaToolchainCompileClasses external/rules_java+/toolchains/platformclasspath_classes; 0s disk-cache, processwrapper-sandbox ... (2 actions running)
[14 / 16] JavaToolchainCompileBootClasspath external/rules_java+/toolchains/platformclasspath.jar; 0s disk-cache, processwrapper-sandbox
INFO: Found 1 target...
Target //:license.check.license_check up-to-date:
  bazel-bin/license.check.license_check
  bazel-bin/license.check.license_check.jar
[16 / 16] no actions running
INFO: Elapsed time: 24.436s, Critical Path: 2.38s
INFO: 16 processes: 12 internal, 3 processwrapper-sandbox, 1 worker.
INFO: Build completed successfully, 16 total actions
INFO: Running command line: bazel-bin/license.check.license_check ./formatted.txt <args omitted>
usage: org.eclipse.dash.licenses.cli.Main [-batch <int>] [-cd <url>]
       [-confidence <int>] [-ef <url>] [-excludeSources <sources>] [-help] [-lic
       <url>] [-project <shortname>] [-repo <url>] [-review] [-summary <file>]
       [-timeout <seconds>] [-token <token>]

@github-actions

Copy link
Copy Markdown

The created documentation from the pull request is available at: docu-html

}
}

void set_process_name()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we could remove this. This is not required for the functionality. In some other sample app we had this only for some demo purpose.

@NicolasFussberger NicolasFussberger left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good to me @Narasimha2211. Thanks for your contribution!
I only added a minor comment.

Please ensure you have an eclipse account linked to your github account so that we can merge your contribution

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

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

Create example app for Alive API

3 participants