Skip to content

Implement new control API - #489

Open
danth wants to merge 5 commits into
eclipse-score:mainfrom
etas-contrib:control-api
Open

Implement new control API#489
danth wants to merge 5 commits into
eclipse-score:mainfrom
etas-contrib:control-api

Conversation

@danth

@danth danth commented Aug 18, 2026

Copy link
Copy Markdown
Member

This pull request adapts the launch manager (and tests) to use the new control API based on mw::com, and removes the old API.

Notable points

  • The State_Manager application type is now aliased to Reporting_and_Supervised.

    Instead, mw::com access control must be used to prevent unwanted processes acting as state managers.

  • The process_fd_leak test is broken because the service provider leaves various file descriptors open. Passing these to child processes is undesirable, and probably a security issue.

    • mw::com does not set O_CLOEXEC by default, and I couldn't find any option to enable it.
    • Closing the service provider by using its class methods between fork and execve is not possible because mw::com has no signal safety guarantees.
    • Trying to close every possible file descriptor in a loop is far too slow.

    I would appreciate any suggestions to fix this :))

  • External documentation needs to be updated before this is released.

Relevant issues

@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

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.7.0) and connecting to it...
INFO: Invocation ID: 888f0780-f607-43de-9fe8-7fb3cd200f21
Computing main repo mapping: 
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: 
Loading: 0 packages loaded
    currently loading: 
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 (51 packages loaded, 10 targets configured)

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

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

Analyzing: target //:license-check (156 packages loaded, 4383 targets configured)

Analyzing: target //:license-check (158 packages loaded, 8562 targets configured)

Analyzing: target //:license-check (163 packages loaded, 9368 targets configured)

Analyzing: target //:license-check (169 packages loaded, 9541 targets configured)

Analyzing: target //:license-check (172 packages loaded, 11426 targets configured)

INFO: Analyzed target //:license-check (173 packages loaded, 11555 targets configured).
[12 / 16] Creating runfiles tree bazel-out/k8-opt-exec-ST-d57f47055a04/bin/external/score_tooling+/dash/tool/formatters/dash_format_converter.runfiles [for tool]; 0s local ... (2 actions, 1 running)
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
INFO: Elapsed time: 25.810s, Critical Path: 0.69s
INFO: 16 processes: 4 disk cache hit, 12 internal.
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>]

@danth
danth requested a deployment to workflow-approval August 18, 2026 13:40 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 18, 2026 13:40 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 18, 2026 13:42 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 18, 2026 13:42 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 19, 2026 08:17 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 19, 2026 08:17 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 19, 2026 10:01 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 19, 2026 10:01 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 19, 2026 13:33 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 19, 2026 13:33 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 21, 2026 15:00 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 21, 2026 15:00 — with GitHub Actions Waiting
@danth

danth commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

I'm marking this as ready for review because the main implementation is complete, so it would be nice to get some feedback.

However, there are still some outstanding points to work on.

Comment thread score/launch_manager/src/daemon/src/control/icontrollable_graph.hpp
Comment thread score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp Outdated
const auto result = skeleton_.activate_run_target.RegisterHandler(
[this](ActivateRunTargetResponse& response, const ActivateRunTargetRequest& request) {
SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE(
request.mode == ActivationMode::kForced, "Only ActivationMode::kForced is implemented");

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.

Maybe I'd log just a warning that queued requests are not implemented yet.
Otherwise people will stumble over crashing LCM when first trying the API given that by default force = false.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think then there is a risk that people expect force = false to behave like force = true, and we break their code when we start implementing it properly.

We could move the assertion to the client side library to make the failure more obvious?

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.

Yeah you are right.
I would still say an assertion is maybe too harsh, as it just crashes the process.

Two alternatives come to mind:

  • Just return an error when activate_run_target is called with force=false
  • Introduce a separate method in the API activate_run_target_force and comment out the generic one for now. Once the force flag is implemented, we can deprecate activate_run_target_force and enable the generic activate_run_target with force parameter.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

A separate method seems easiest. I think that will actually be more readable in the client code compared to a bool flag. Maybe we should keep it separate even once both are implemented?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Opened #621.

Comment thread score/launch_manager/src/daemon/src/process_group_manager/control_provider.cpp Outdated
Comment thread score/launch_manager/src/daemon/src/control/control_provider.hpp
Comment thread score/launch_manager/src/daemon/src/control/icontrollable_graph.hpp
"binary_name": "control_client_test_driver",
"application_profile": {
"application_type": "State_Manager",
"application_type": "Reporting_And_Supervised",

@NicolasFussberger NicolasFussberger Sep 7, 2026

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 am not sure if we should remove the application type "State Manager".
You are right that currently technically there is no difference to Reporting_And_Supervised because the access to the mw::com service instance is separately configured in a mw::com config file. It could be treated in code as synonymous to Reporting_And_Supervised.
However, I wonder if at some point we could generate this config or there could be other IPC implementations in the future that will need to know which process requires access to the state manager interface.

One idea (though I am not sure here) could be to use the new mw::com Addon configuration to configure the mw::com service within the launch manager code. We could derive the access restrictions from the StateManager in our json file.
On the other hand this also limits the flexibility of the integrator, as you cannot easily play with the config options if its hardcoded in launch manager code.

What do you think @SimonKozik ?

@danth danth Sep 7, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

However, I wonder if at some point we could generate this config

On the state manager side, the config file is shared with any other mw::com usage. I think we should avoid managing their config because it would make it difficult for the user to write a state manager which also interacts with other services in addition to launch manager.


Aside:

If we remove the State_Manager option, the application type could later be replaced by two booleans:

{
  "application_profile": {
    "is_reporting": true,
    "is_supervised": false,
  }
}

This would make it possible to have a component which is supervised but not reporting. Any program which has report_ready as its first line, meaning there is no real setup being waited for, could just not report at all, while still having supervision.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It could be treated in code as synonymous to Reporting_And_Supervised.

I've implemented it this way for now, to reduce the scope of this pull request.

We can consider changing the schema separately.

@WilliamRoebuck WilliamRoebuck 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.

A really great implementation, I have some small cleanup suggestions. I also rambled a bit about the API but I understand I may be a bit late on this so apologies if it's not relevant. As I'll be away from tomorrow, just comment and resolve if you disagree or I've misunderstood

Comment thread score/launch_manager/src/daemon/src/process_group_manager/control_provider.cpp Outdated
Comment thread score/launch_manager/src/daemon/src/process_group_manager/control_provider.cpp Outdated
// workaround to detect we're in fallback
// This verifies that a fallback process was actually started - the launch manager
// did not just send an event without taking the action.
EXPECT_TRUE(std::filesystem::exists(fallback_file)) << "Fallback run target was not activated";

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.

Can we just use get_active_run_target() here? Rather than repeating this step each test, we could have a single test to verify that a component configured to launch in fallback actually launched

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I tried to make minimal changes from the old tests, but this can be cleaned up.

I think we should have a separate test which makes sure that the callbacks are telling the truth, then no further verification is needed in the other tests.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think these improvements could be done in a separate pull request, so long as the tests are passing in their current state. :))

Comment thread tests/utils/test_helper/test_helper.hpp
Comment thread examples/control_application/control_daemon.cpp
case fb::ApplicationType::Reporting_And_Supervised:
return ApplicationType::ReportingAndSupervised;
case fb::ApplicationType::State_Manager:
return ApplicationType::StateManager;

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 would recommend to translate fb::ApplicationType::State_Manager into ApplicationType::ReportingAndSupervised until we remove State_Manager from configuration schema.

Additionally we probably need to create work item to change configuration schema and to adapt translation script scripts/config_mapping/lifecycle_config.py

const ActivateRunTargetRequest& request)
{
SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE(
request.mode == ActivationMode::kForced, "Only ActivationMode::kForced is implemented");

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.

If we don't have a work item already, we should create one.

The queue is the intended mode and forced flag should be used sparingly...

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.

Initial implementation of mw::com-based control API (daemon) Create a design for using mw::com for Control API

5 participants