Skip to content

Introduce new Component class - #705

Draft
danth wants to merge 15 commits into
eclipse-score:mainfrom
etas-contrib:pin-split
Draft

danth wants to merge 15 commits into
eclipse-score:mainfrom
etas-contrib:pin-split

Conversation

@danth

@danth danth commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Start, stop, force stop, and ready conditions are now implemented as strategies which plug in to a central Component class.

The only interaction between these classes is a tiny Handle struct, which identifies the child process to act upon.

Ideally, the handle will stay internal to the Component, and higher level classes such as ProcessGroupManager and the Graph will have no knowledge of the underlying process.

This new architecture should improve:

  • ProcessInfoNode having a mixture of process- and component-level code.
  • ProcessLauncher also having code for process termination.
  • Difficulty in adding new ready conditions and component types.

As a start, this pull request just introduces the new classes, and has them call the existing ProcessLauncher from its original location.

Once the new component class is ready, we can change the Graph to start using it in place of ProcessInfoNode. Currently it is unused outside of tests.

Finally, we will clean up by moving the old code into its new locations (rather than just calling it).


for (const IReadyCondition* ready_condition : ready_conditions_)
{
const osal::OsalReturnType result = ready_condition->wait(handle_.value());

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.

Currently we have one overall ready timeout for the component.

if we had multiple ready conditions, I think this would mean all ready condition must be fulfilled within the ready_timeout. So it would not be that each ready condition can take the full ready timeout.

This makes me think that it could make sense to move the timeout checking in the component. Same for the shutdown timeout

{
return score::cpp::make_unexpected(ComponentError::kErrorBeforeReady);
}
handle_ = result.value();

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 wonder how to handle the case that the component crashes before ready condition is fulfilled.
Is this in the responsibility of each ready condition to continuously check if the component is still running?

}

Component::Component(
const IStartAction* start_action,

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.

With the division into start/stop actions I am wondering what is keeping track of the process state.
What will own the process handle?

I think at every point in time we need to know what is the state of any process we started, and what is the state of the component

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.

The handle is owned by the component, and should track the state of the underlying resource (a process, a container, etc) but not the state of the component itself. It may be useful to make the handle mutable, for example to clear the PID if the process has crashed.

Currently the state at the component level is just whether or not a handle currently exists. But this should be extended to an enum such as starting, stopping, failed... which is updated as we run each action and in response to external events.

return score::cpp::make_unexpected(ComponentError::kErrorAfterReady);
}

IComponent::RequestResult Component::tryHandleTermination(int32_t status)

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 wonder how to judge now if the process crashed or was intentionally terminated (as the result of the stop_action/force_stop_action or the process is configured as self-terminating and we are waiting for this in the ready condition).

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.

Similar to the other comment, we could store this state at the component level.


if (process.pid > 0)
{
if (kill(process.pid, SIGTERM) == 0)

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'll need to decide where the timeout monitoring takes place for the shutdown and the escalation to SIGKILL in case of timeout

return score::cpp::make_unexpected(ComponentError::kActivationTimedOut);
}
}

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'll need to decide how the supervision is handled.
I think a natural point would be to start supervision here after all ready conditions are fulfilled.

Currently, this will always translate to start supervision when kRunning reported.

Though for this we also need the timestamp from the kRunning report, as the supervision has to be started exactly at this timestamp.

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.

Maybe it would be possible to have IpcCommsSync store the timestamp (as it should happen only once per instance). That is already stored inside ProcessHandle, so it would be accessible to the supervision.

@danth danth changed the title Refactor ProcessInfoNode and ProcessLauncher Introduce new Component class Sep 30, 2026
@danth
danth requested a deployment to workflow-approval October 2, 2026 09:49 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval October 2, 2026 09:49 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval October 2, 2026 09:51 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval October 2, 2026 09:51 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval October 2, 2026 09:51 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval October 2, 2026 09:51 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval October 2, 2026 10:05 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval October 2, 2026 10:05 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval October 2, 2026 10:05 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval October 2, 2026 10:05 — with GitHub Actions Waiting
danth added 15 commits October 2, 2026 16:31
This uses the existing component interface, so it should be fully
compatible with existing callers.
This will be needed to remove the direct use of process identifiers
in `Graph::forceKillProcesses`, making it flexible to other kinds
of components.
These will be used for run targets, which do not contain any
underlying process.
These use the existing `ProcessLauncher` for the time being;
eventually the code from `ProcessLauncher` should be migrated
into the actions themselves.
Follow the naming conventions.

This branch is waiting to be deployed

1 waiting deployment
workflow-approval — 04bc7e96 Waiting Oct 2, 2026 by danth via Build and test arm64-qnx / approval #1203
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.

3 participants