Implement new control API - #489
Conversation
License Check Results🚀 The license check job ran with the Bazel command: bazel run --lockfile_mode=error //:license-checkStatus: Click to expand output |
|
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. |
| 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"); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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_forceand comment out the generic one for now. Once the force flag is implemented, we can deprecateactivate_run_target_forceand enable the genericactivate_run_targetwith force parameter.
There was a problem hiding this comment.
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?
| "binary_name": "control_client_test_driver", | ||
| "application_profile": { | ||
| "application_type": "State_Manager", | ||
| "application_type": "Reporting_And_Supervised", |
There was a problem hiding this comment.
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 ?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
left a comment
There was a problem hiding this comment.
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
| // 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"; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I think these improvements could be done in a separate pull request, so long as the tests are passing in their current state. :))
This works around the `Graph` class not being thread safe.
| case fb::ApplicationType::Reporting_And_Supervised: | ||
| return ApplicationType::ReportingAndSupervised; | ||
| case fb::ApplicationType::State_Manager: | ||
| return ApplicationType::StateManager; |
There was a problem hiding this comment.
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"); |
There was a problem hiding this comment.
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...
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_Managerapplication type is now aliased toReporting_and_Supervised.Instead,
mw::comaccess control must be used to prevent unwanted processes acting as state managers.The
process_fd_leaktest is broken because the service provider leaves various file descriptors open. Passing these to child processes is undesirable, and probably a security issue.mw::comdoes not setO_CLOEXECby default, and I couldn't find any option to enable it.forkandexecveis not possible becausemw::comhas no signal safety guarantees.closeevery 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