From 10a995a985466f5ab657031d765eb313f6a17fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20Fu=C3=9Fberger?= Date: Tue, 9 Jun 2026 07:21:23 +0200 Subject: [PATCH 01/13] Refactor and rename ProcessStateClient --- score/launch_manager/src/daemon/BUILD | 2 +- .../details/daemon/AliveMonitorImpl.cpp | 6 +- .../details/daemon/AliveMonitorImpl.hpp | 6 +- .../details/daemon/PhmDaemon.cpp | 2 +- .../details/daemon/PhmDaemon.hpp | 4 +- .../details/ifappl/MonitorIfDaemon.cpp | 7 +- .../details/ifappl/MonitorIfDaemon_UT.cpp | 48 ++---- .../src/alive_monitor/details/ifexm/BUILD | 4 +- .../details/ifexm/ProcessState.cpp | 8 +- .../details/ifexm/ProcessState.hpp | 35 ++-- .../details/ifexm/ProcessStateReader.cpp | 62 ++----- .../details/ifexm/ProcessStateReader.hpp | 30 ++-- .../details/supervision/Alive.cpp | 33 ++-- .../details/supervision/Alive.hpp | 12 +- .../details/supervision/Alive_UT.cpp | 80 ++-------- .../src/daemon/src/common/BUILD | 8 + .../src/daemon/src/common/process_state.hpp | 39 +++++ .../src/daemon/src/configuration/BUILD | 4 +- .../configuration/configuration_adapter.hpp | 2 +- score/launch_manager/src/daemon/src/main.cpp | 13 +- .../daemon/src/process_group_manager/BUILD | 2 +- .../src/process_group_manager/details/BUILD | 2 +- .../process_group_manager/details/graph.cpp | 6 +- .../process_group_manager/details/graph.hpp | 6 +- .../details/graph_UT.cpp | 12 +- .../details/process_info_node.cpp | 17 +- .../process_group_manager.cpp | 6 +- .../process_group_manager.hpp | 30 ++-- .../src/daemon/src/process_state_client/BUILD | 85 ---------- .../details/process_state_receiver.hpp | 72 --------- .../iprocess_state_notifier.hpp | 55 ------- .../iprocess_state_receiver.hpp | 48 ------ .../process_state_client/posix_process.hpp | 81 ---------- .../process_state_client_ut.cpp | 151 ------------------ .../process_state_notifier.hpp | 86 ---------- .../src/supervision_control_client/BUILD | 83 ++++++++++ .../details/BUILD | 14 +- .../details/supervision_control_receiver.cpp} | 22 +-- .../details/supervision_control_receiver.hpp | 68 ++++++++ .../isupervision_control_notifier.hpp | 48 ++++++ .../isupervision_control_receiver.hpp | 46 ++++++ .../supervision_control_client_ut.cpp | 135 ++++++++++++++++ .../supervision_control_notifier.cpp} | 18 +-- .../supervision_control_notifier.hpp | 75 +++++++++ .../supervision_event.hpp | 58 +++++++ 45 files changed, 742 insertions(+), 889 deletions(-) create mode 100644 score/launch_manager/src/daemon/src/common/process_state.hpp delete mode 100644 score/launch_manager/src/daemon/src/process_state_client/BUILD delete mode 100644 score/launch_manager/src/daemon/src/process_state_client/details/process_state_receiver.hpp delete mode 100644 score/launch_manager/src/daemon/src/process_state_client/iprocess_state_notifier.hpp delete mode 100644 score/launch_manager/src/daemon/src/process_state_client/iprocess_state_receiver.hpp delete mode 100644 score/launch_manager/src/daemon/src/process_state_client/posix_process.hpp delete mode 100644 score/launch_manager/src/daemon/src/process_state_client/process_state_client_ut.cpp delete mode 100644 score/launch_manager/src/daemon/src/process_state_client/process_state_notifier.hpp create mode 100644 score/launch_manager/src/daemon/src/supervision_control_client/BUILD rename score/launch_manager/src/daemon/src/{process_state_client => supervision_control_client}/details/BUILD (63%) rename score/launch_manager/src/daemon/src/{process_state_client/details/process_state_receiver.cpp => supervision_control_client/details/supervision_control_receiver.cpp} (55%) create mode 100644 score/launch_manager/src/daemon/src/supervision_control_client/details/supervision_control_receiver.hpp create mode 100644 score/launch_manager/src/daemon/src/supervision_control_client/isupervision_control_notifier.hpp create mode 100644 score/launch_manager/src/daemon/src/supervision_control_client/isupervision_control_receiver.hpp create mode 100644 score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp rename score/launch_manager/src/daemon/src/{process_state_client/process_state_notifier.cpp => supervision_control_client/supervision_control_notifier.cpp} (60%) create mode 100644 score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.hpp create mode 100644 score/launch_manager/src/daemon/src/supervision_control_client/supervision_event.hpp diff --git a/score/launch_manager/src/daemon/BUILD b/score/launch_manager/src/daemon/BUILD index 83e3888bb2..47903a6e3c 100644 --- a/score/launch_manager/src/daemon/BUILD +++ b/score/launch_manager/src/daemon/BUILD @@ -28,7 +28,7 @@ cc_binary( "//score/launch_manager/src/daemon/src/osal:ipc_comms", "//score/launch_manager/src/daemon/src/process_group_manager", "//score/launch_manager/src/daemon/src/process_group_manager:alive_monitor_thread", - "//score/launch_manager/src/daemon/src/process_state_client:process_state_notifier", + "//score/launch_manager/src/daemon/src/supervision_control_client:supervision_control_notifier", "//score/launch_manager/src/daemon/src/recovery_client", "//score/launch_manager/src/daemon/src/watchdog:watchdog_factory", "@score_baselibs//score/language/futurecpp", diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp index cd21a81d79..819b01035c 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp @@ -29,7 +29,7 @@ namespace daemon AliveMonitorImpl::AliveMonitorImpl( SptrIRecoveryClient recovery_client, - UptrIProcessStateReceiver process_state_receiver, + UptrISupervisionControlReceiver process_state_receiver, const Config& config) : m_recovery_client(recovery_client), m_process_state_receiver(std::move(process_state_receiver)), @@ -45,7 +45,11 @@ EInitCode AliveMonitorImpl::init() noexcept m_osClock.startMeasurement(); m_daemon = std::make_unique(m_osClock, std::move(m_process_state_receiver)); +#ifdef USE_NEW_CONFIGURATION initResult = m_daemon->init(m_recovery_client, m_config); +#else + initResult = m_daemon->init(m_recovery_client); +#endif if (initResult == EInitCode::kNoError) { diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.hpp index ddcc103e0a..152eca1faf 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.hpp @@ -34,7 +34,7 @@ namespace daemon { using SptrIRecoveryClient = std::shared_ptr; -using UptrIProcessStateReceiver = std::unique_ptr; +using UptrISupervisionControlReceiver = std::unique_ptr; using UptrPhmDaemon = std::unique_ptr; using OsClock = score::lcm::saf::timers::OsClockInterface; using Config = score::mw::launch_manager::configuration::Config; @@ -45,7 +45,7 @@ class AliveMonitorImpl : public IAliveMonitor public: AliveMonitorImpl( SptrIRecoveryClient recovery_client, - UptrIProcessStateReceiver process_state_receiver, + UptrISupervisionControlReceiver process_state_receiver, const Config& config); EInitCode init() noexcept override; @@ -56,7 +56,7 @@ class AliveMonitorImpl : public IAliveMonitor SptrIRecoveryClient m_recovery_client{nullptr}; UptrPhmDaemon m_daemon{nullptr}; OsClock m_osClock{}; - UptrIProcessStateReceiver m_process_state_receiver; + UptrISupervisionControlReceiver m_process_state_receiver; AliveMonitorConfig m_config; }; diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.cpp index ce1f9f8e11..01b9a9ab99 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.cpp @@ -31,7 +31,7 @@ namespace daemon true_no_defect) */ /* RULECHECKER_comment(0, 4, check_incomplete_data_member_construction, "Default constructor is used for\ processStateReader.", true_no_defect) */ -PhmDaemon::PhmDaemon(OsClock& f_osClock, std::unique_ptr f_process_state_receiver) +PhmDaemon::PhmDaemon(OsClock& f_osClock, std::unique_ptr f_process_state_receiver) : osClock{f_osClock}, cycleTimer{&osClock}, swClusterHandlers{}, diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp index 7a9bedf5f4..c388745764 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp @@ -53,7 +53,7 @@ class PhmDaemon { public: using OsClock = score::lcm::saf::timers::OsClockInterface; - using ProcessStateReceiver = score::lcm::IProcessStateReceiver; + using ProcessStateReceiver = score::lcm::ISupervisionControlReceiver; using RecoveryClient = score::lcm::IRecoveryClient; using SupervisionBufferConfig = factory::SupervisionBufferConfig; using CycleTimer = score::lcm::saf::timers::CycleTimer; @@ -70,7 +70,7 @@ class PhmDaemon /// tests) /* RULECHECKER_comment(3,1, check_expensive_to_copy_in_parameter, "Move only types cannot be passed by const ref", true_no_defect) */ - PhmDaemon(OsClock& f_osClock, std::unique_ptr f_process_state_receiver); + PhmDaemon(OsClock& f_osClock, std::unique_ptr f_process_state_receiver); /* RULECHECKER_comment(0, 4, check_min_instructions, "Default destructor is not provided\ a function body", true_no_defect) */ diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.cpp index 1640908c5d..6cbd78ff46 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.cpp @@ -44,10 +44,9 @@ void MonitorIfDaemon::attachCheckpoint(Checkpoint& f_checkpoint_r) noexcept(fals void MonitorIfDaemon::updateData(const ifexm::ProcessState& f_observable_r) noexcept(true) { - ifexm::ProcessState::EProcState state{f_observable_r.getState()}; - static constexpr ifexm::ProcessState::EProcState kInitState = ifexm::ProcessState::EProcState::starting; + const score::lcm::SupervisionEventType eventType{f_observable_r.getEventType()}; - if ((kInitState == state) || (ifexm::ProcessState::EProcState::running == state)) + if (eventType == score::lcm::SupervisionEventType::kActivation) { if (isDeactivateRequest) { @@ -56,7 +55,7 @@ void MonitorIfDaemon::updateData(const ifexm::ProcessState& f_observable_r) noex isActivateRequest = true; isDeactivateRequest = false; } - else if (ifexm::ProcessState::EProcState::off == state) + else if (eventType == score::lcm::SupervisionEventType::kDeactivation) { isDeactivateRequest = true; } diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon_UT.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon_UT.cpp index d1d1ec42ec..96992361a1 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon_UT.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon_UT.cpp @@ -78,27 +78,19 @@ struct MonitorIfDaemonFixture << "CheckpointIpcServer init failed"; } - /// Drive the process to the 'running' state and notify observers. + /// Send an activation event and notify observers. void activateProcess(timers::NanoSecondType ts) { processState.setTimestamp(ts); - processState.setState(ifexm::ProcessState::EProcState::running); + processState.setEventType(score::lcm::SupervisionEventType::kActivation); processState.pushData(); } - /// Drive the process to the 'starting' state and notify observers. - void startProcess(timers::NanoSecondType ts) - { - processState.setTimestamp(ts); - processState.setState(ifexm::ProcessState::EProcState::starting); - processState.pushData(); - } - - /// Drive the process to the 'off' state and notify observers. + /// Send a deactivation event and notify observers. void deactivateProcess(timers::NanoSecondType ts) { processState.setTimestamp(ts); - processState.setState(ifexm::ProcessState::EProcState::off); + processState.setEventType(score::lcm::SupervisionEventType::kDeactivation); processState.pushData(); } @@ -185,7 +177,7 @@ TEST_F(MonitorIfDaemonTest, InitiallyInactive_CheckForNewData_DoesNotNotifyCheck { RecordProperty( "Description", - "Before any process-state update the monitor is kInactive; " + "Before any supervision event the monitor is kInactive; " "checkForNewData must not forward any data."); MonitorIfDaemonFixture fix; @@ -193,11 +185,11 @@ TEST_F(MonitorIfDaemonTest, InitiallyInactive_CheckForNewData_DoesNotNotifyCheck fix.monitor.checkForNewData(mockClock()); } -TEST_F(MonitorIfDaemonTest, ProcessOffBeforeActivation_RemainsInactive) +TEST_F(MonitorIfDaemonTest, DeactivationBeforeActivation_RemainsInactive) { RecordProperty( "Description", - "A process-off event before the monitor has been activated " + "A deactivation event before the monitor has been activated " "must not cause checkForNewData to read IPC data."); MonitorIfDaemonFixture fix; @@ -210,11 +202,11 @@ TEST_F(MonitorIfDaemonTest, ProcessOffBeforeActivation_RemainsInactive) fix.monitor.checkForNewData(mockClock()); } -TEST_F(MonitorIfDaemonTest, ProcessRunning_ActivatesMonitorOnNextCheckForNewData) +TEST_F(MonitorIfDaemonTest, ActivationEvent_ActivatesMonitorOnNextCheckForNewData) { RecordProperty( "Description", - "A running process-state update must set isActivateRequest so that " + "An activation event must set isActivateRequest so that " "the next checkForNewData transitions the monitor to kActive."); MonitorIfDaemonFixture fix; @@ -228,29 +220,11 @@ TEST_F(MonitorIfDaemonTest, ProcessRunning_ActivatesMonitorOnNextCheckForNewData EXPECT_EQ(fix.checkpoint.getTimestamp(), checkpoint_time); } -TEST_F(MonitorIfDaemonTest, ProcessStarting_AlsoActivatesMonitor) -{ - RecordProperty( - "Description", - "EProcState::starting must be treated as an activation trigger, " - "identical to running."); - - MonitorIfDaemonFixture fix; - EXPECT_CALL(fix.checkpointMock, updateData).Times(1); - fix.initIpc(); - fix.startProcess(mockClock()); - const auto checkpoint_time = mockClockOffset(); - fix.sendCheckpoint(MonitorIfDaemonFixture::kCheckpointId, checkpoint_time); - fix.monitor.checkForNewData(mockClock()); - - EXPECT_EQ(fix.checkpoint.getTimestamp(), checkpoint_time); -} - -TEST_F(MonitorIfDaemonTest, ProcessOff_DeactivatesMonitor_NoFurtherDataForwarded) +TEST_F(MonitorIfDaemonTest, DeactivationEvent_DeactivatesMonitor_NoFurtherDataForwarded) { RecordProperty( "Description", - "After a process-off event checkForNewData drains the IPC for the " + "After a deactivation event checkForNewData drains the IPC for the " "current cycle, then transitions to kInactive. Subsequent cycles " "must not forward data even when the IPC buffer is non-empty."); diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/BUILD b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/BUILD index 71fa233823..cb780aa9aa 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/BUILD +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/BUILD @@ -36,7 +36,7 @@ cc_library( "//score/launch_manager/src/daemon/src/alive_monitor/details/common:observer", "//score/launch_manager/src/daemon/src/alive_monitor/details/common:types", "//score/launch_manager/src/daemon/src/alive_monitor/details/timers:timers_os_clock", - "//score/launch_manager/src/daemon/src/process_state_client", + "//score/launch_manager/src/daemon/src/supervision_control_client", ], ) @@ -53,6 +53,6 @@ cc_library( "//score/launch_manager/src/daemon/src/alive_monitor/details/timers:time_conversion", "//score/launch_manager/src/daemon/src/alive_monitor/details/timers:timers_os_clock", "//score/launch_manager/src/daemon/src/common:log", - "//score/launch_manager/src/daemon/src/process_state_client", + "//score/launch_manager/src/daemon/src/supervision_control_client", ], ) diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessState.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessState.cpp index 4fb675ba43..a04039edb7 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessState.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessState.cpp @@ -40,14 +40,14 @@ common::ProcessId ProcessState::getProcessId() const noexcept return k_processId; } -ProcessState::EProcState ProcessState::getState() const noexcept +score::lcm::SupervisionEventType ProcessState::getEventType() const noexcept { - return eProcState; + return eventType_; } -void ProcessState::setState(ProcessState::EProcState f_processStateId) noexcept +void ProcessState::setEventType(score::lcm::SupervisionEventType f_eventType) noexcept { - eProcState = f_processStateId; + eventType_ = f_eventType; } timers::NanoSecondType ProcessState::getTimestamp() const noexcept diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessState.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessState.hpp index a4354073aa..2a5cae5fc9 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessState.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessState.hpp @@ -20,7 +20,7 @@ #include "score/mw/launch_manager/alive_monitor/details/timers/Timers_OsClock.hpp" #include -#include "score/mw/launch_manager/process_state_client/posix_process.hpp" +#include "score/mw/launch_manager/supervision_control_client/supervision_event.hpp" namespace score { @@ -32,7 +32,7 @@ namespace ifexm { /// @brief Process State -/// @details The Process State class dispatches process state changes to the attached observers. +/// @details The Process State class dispatches supervision events to the attached observers. class ProcessState : public saf::common::Observable { public: @@ -72,24 +72,13 @@ class ProcessState : public saf::common::Observable /// @return Returns process ID common::ProcessId getProcessId(void) const noexcept; - /// @brief Enumeration of process states - enum class EProcState : uint8_t - { - idle = static_cast(score::lcm::ProcessState::kIdle), - starting = static_cast(score::lcm::ProcessState::kStarting), - running = static_cast(score::lcm::ProcessState::kRunning), - sigterm = static_cast(score::lcm::ProcessState::kTerminating), - off = static_cast(score::lcm::ProcessState::kTerminated), - failed = static_cast(score::lcm::ProcessState::kFailed) - }; - - /// @brief Get Process State - /// @return Returns Process State - EProcState getState() const noexcept; - - /// @brief Set process state - /// @param [in] f_processStateId Process state id - void setState(ProcessState::EProcState f_processStateId) noexcept; + /// @brief Get supervision event type + /// @return Returns the current event type + score::lcm::SupervisionEventType getEventType() const noexcept; + + /// @brief Set supervision event type + /// @param [in] f_eventType Supervision event type + void setEventType(score::lcm::SupervisionEventType f_eventType) noexcept; /// @brief Get Timestamp for current event /// @return Timestamp of current event @@ -100,7 +89,7 @@ class ProcessState : public saf::common::Observable void setTimestamp(timers::NanoSecondType f_timestamp) noexcept; /// @brief Push Data - /// @details Push process state related information, which shall be distribute to observers. + /// @details Push supervision event related information, which shall be distributed to observers. void pushData(void) noexcept; private: @@ -110,8 +99,8 @@ class ProcessState : public saf::common::Observable /// @brief Process id const common::ProcessId k_processId; - /// @brief Current process state - EProcState eProcState{ProcessState::EProcState::idle}; + /// @brief Current supervision event type + score::lcm::SupervisionEventType eventType_{score::lcm::SupervisionEventType::kDeactivation}; /// @brief Current timestamp of process timers::NanoSecondType timestamp{UINT64_MAX}; diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.cpp index e666e8ebc9..14683aceef 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.cpp @@ -70,29 +70,27 @@ bool ProcessStateReader::distributeChanges(const timers::NanoSecondType f_syncTi bool flagContinue{true}; do { - score::Result> resultChangedProcess{ - processStateReceiverHM->getNextChangedPosixProcess()}; + score::Result> resultEvent{ + processStateReceiverHM->getNextSupervisionEvent()}; - if (resultChangedProcess) + if (resultEvent) { - const auto changedPosixProcess{resultChangedProcess.value()}; - if (changedPosixProcess) + const auto event{resultEvent.value()}; + if (event) { - LM_LOG_DEBUG() << "Process with Id" << changedPosixProcess->id << "changed state PG" - << changedPosixProcess->processGroupStateId << "PS" - << static_cast(changedPosixProcess->processStateId); - isPushPending = pushUpdateTill(*changedPosixProcess, f_syncTimestamp); + LM_LOG_DEBUG() << "Process with Id" << event->id << "received supervision event" + << static_cast(event->eventType); + isPushPending = pushUpdateTill(*event, f_syncTimestamp); flagContinue = (!isPushPending); } else { - // No more process to be parsed by PHM flagContinue = false; } } else { - LM_LOG_ERROR() << "Process State Reader failed with error:" << resultChangedProcess.error().Message(); + LM_LOG_DEBUG() << "Process State Reader failed with error:" << resultEvent.error().Message(); flagContinue = false; flagSuccess = false; } @@ -102,26 +100,26 @@ bool ProcessStateReader::distributeChanges(const timers::NanoSecondType f_syncTi } bool ProcessStateReader::pushUpdateTill( - const ProcessStateReader::LcmPosixProcess& f_changedPosixProcess_r, + const LcmSupervisionEvent& f_event, const timers::NanoSecondType f_syncTimestamp) noexcept { bool isSyncTimestampReached{false}; - const common::ProcessId processId{f_changedPosixProcess_r.id.data()}; + const common::ProcessId processId{f_event.id.data()}; std::map::iterator processMapIterator{processStateMap.find(processId)}; if (processMapIterator != processStateMap.end()) { - processMapIterator->second->setState(translateProcessState(f_changedPosixProcess_r.processStateId)); + processMapIterator->second->setEventType(f_event.eventType); timers::NanoSecondType changedProcessTimestamp{ - timers::TimeConversion::convertToNanoSec(f_changedPosixProcess_r.systemClockTimestamp)}; + timers::TimeConversion::convertToNanoSec(f_event.systemClockTimestamp)}; processMapIterator->second->setTimestamp(changedProcessTimestamp); - // If process state change occurred before synchronization timestamp, push data for current cycle. + // If event occurred before synchronization timestamp, push data for current cycle. if (changedProcessTimestamp <= f_syncTimestamp) { processMapIterator->second->pushData(); } - // If process state change occurred after synchronization timestamp, push data in the beginning of next cycle. + // If event occurred after synchronization timestamp, push data in the beginning of next cycle. else { lastChangedProcess_p = processMapIterator->second; @@ -131,36 +129,6 @@ bool ProcessStateReader::pushUpdateTill( return isSyncTimestampReached; } -constexpr ProcessState::EProcState ProcessStateReader::translateProcessState( - const ProcessStateReader::LcmProcessState f_processStateLcm) noexcept -{ - // Following static assertion ensures consistency of process states in EXM and PHM - static_assert( - static_cast(ProcessState::EProcState::idle) == static_cast(score::lcm::ProcessState::kIdle), - "Lcm State Enum and ProcessState::EProcState Enum do not match."); - static_assert( - static_cast(ProcessState::EProcState::starting) == - static_cast(score::lcm::ProcessState::kStarting), - "Lcm State Enum and ProcessState::EProcState Enum do not match."); - static_assert( - static_cast(ProcessState::EProcState::running) == - static_cast(score::lcm::ProcessState::kRunning), - "Lcm State Enum and ProcessState::EProcState Enum do not match."); - static_assert( - static_cast(ProcessState::EProcState::sigterm) == - static_cast(score::lcm::ProcessState::kTerminating), - "Lcm State Enum and ProcessState::EProcState Enum do not match."); - static_assert( - static_cast(ProcessState::EProcState::off) == - static_cast(score::lcm::ProcessState::kTerminated), - "Lcm State Enum and ProcessState::EProcState Enum do not match."); - static_assert( - static_cast(ProcessState::EProcState::failed) == - static_cast(score::lcm::ProcessState::kFailed), - "Lcm State Enum and ProcessState::EProcState Enum do not match."); - return static_cast(f_processStateLcm); -} - } // namespace ifexm } // namespace saf } // namespace lcm diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.hpp index 9ad66bf545..3845917cd3 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.hpp @@ -19,8 +19,8 @@ #include "score/mw/launch_manager/alive_monitor/details/common/Types.hpp" #include "score/mw/launch_manager/alive_monitor/details/ifexm/ProcessState.hpp" #include "score/mw/launch_manager/alive_monitor/details/timers/Timers_OsClock.hpp" -#include "score/mw/launch_manager/process_state_client/iprocess_state_receiver.hpp" -#include "score/mw/launch_manager/process_state_client/posix_process.hpp" +#include "score/mw/launch_manager/supervision_control_client/isupervision_control_receiver.hpp" +#include "score/mw/launch_manager/supervision_control_client/supervision_event.hpp" namespace score { @@ -32,14 +32,13 @@ namespace ifexm { /// @brief Process State reader -/// @details The Process State reader fetches process state updates via the lcm library and distributes +/// @details The Process State reader fetches supervision events via the lcm library and distributes /// the information to the Process State classes. class ProcessStateReader { public: - using LcmProcessState = score::lcm::ProcessState; - using LcmPosixProcess = score::lcm::PosixProcess; - using LcmProcessStateReceiver = score::lcm::IProcessStateReceiver; + using LcmSupervisionEvent = score::lcm::SupervisionEvent; + using LcmProcessStateReceiver = score::lcm::ISupervisionControlReceiver; /// @brief Constructor /// @param [in] f_process_state_receiver Process state receiver implementation @@ -68,27 +67,20 @@ class ProcessStateReader void deregisterProcessState(const common::ProcessId f_processId) noexcept; /// @brief Distribute changes - /// @details Distribute process state changes to the registered Process State classes + /// @details Distribute supervision events to the registered Process State classes /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization - /// @return true (successful process state distribution), false (failed process state distribution) + /// @return true (successful distribution), false (failed distribution) bool distributeChanges(const timers::NanoSecondType f_syncTimestamp) noexcept; private: /// @brief Push update for changed registered process - /// @param [in] f_changedPosixProcess_r Posix Process for which push update is needed - /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization + /// @param [in] f_event Supervision event for which push update is needed + /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization /// @return true (sync timestamp is reached), false (sync timestamp is not yet reached) - bool pushUpdateTill( - const ProcessStateReader::LcmPosixProcess& f_changedPosixProcess_r, - const timers::NanoSecondType f_syncTimestamp) noexcept; - - /// @brief Translate Lcm State to ProcessState::EProcState - /// @param [in] f_processStateLcm Process state from Lcm - /// @return Process state (e.g: idle, running, off) - static constexpr ProcessState::EProcState translateProcessState(const LcmProcessState f_processStateLcm) noexcept; + bool pushUpdateTill(const LcmSupervisionEvent& f_event, const timers::NanoSecondType f_syncTimestamp) noexcept; /// @brief Process state receiver for HM thread - std::unique_ptr processStateReceiverHM; + std::unique_ptr processStateReceiverHM; /// @brief Map for process id and process state object std::map processStateMap{}; diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.cpp index 4edc205e6d..753d5f1bfb 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.cpp @@ -78,21 +78,12 @@ void Alive::updateData(const score::lcm::saf::ifappl::Checkpoint& f_observable_r // coverity[exn_spec_violation:FALSE] std::length_error is not thrown from push() which uses fixed-size-vector void Alive::updateData(const ifexm::ProcessState& f_observable_r) noexcept(true) { - const ifexm::ProcessState::EProcState state{f_observable_r.getState()}; - - const bool isRelevant = - (state == ifexm::ProcessState::EProcState::running) || (state == ifexm::ProcessState::EProcState::sigterm) || - (state == ifexm::ProcessState::EProcState::failed) || (state == ifexm::ProcessState::EProcState::off); - - if (isRelevant) + const timers::NanoSecondType timestamp{f_observable_r.getTimestamp()}; + SupervisionEventSnapshot snapshot{timestamp, f_observable_r.getEventType()}; + if (!timeSortingUpdateEventBuffer.push(snapshot, timestamp)) { - const timers::NanoSecondType timestamp{f_observable_r.getTimestamp()}; - ProcessStateSnapshot snapshot{timestamp, state}; - if (!timeSortingUpdateEventBuffer.push(snapshot, timestamp)) - { - dataLossReason = EDataLossReason::kBufferFull; - eventTimestamp = lastSyncTimestamp; - } + dataLossReason = EDataLossReason::kBufferFull; + eventTimestamp = lastSyncTimestamp; } } @@ -273,16 +264,14 @@ Alive::EUpdateEventType Alive::getAliveEventType( return EUpdateEventType::kEvaluation; } - if (std::holds_alternative(f_updateEvent)) + if (std::holds_alternative(f_updateEvent)) { - const auto& snapshot = std::get(f_updateEvent); - if (snapshot.eProcState == ifexm::ProcessState::EProcState::running) + const auto& snapshot = std::get(f_updateEvent); + if (snapshot.eventType == score::lcm::SupervisionEventType::kActivation) { return EUpdateEventType::kActivation; } - if (snapshot.eProcState == ifexm::ProcessState::EProcState::sigterm || - snapshot.eProcState == ifexm::ProcessState::EProcState::off || - snapshot.eProcState == ifexm::ProcessState::EProcState::failed) + if (snapshot.eventType == score::lcm::SupervisionEventType::kDeactivation) { return EUpdateEventType::kDeactivation; } @@ -591,9 +580,9 @@ void Alive::logExpiredFailedStateDetails() const noexcept(true) timers::NanoSecondType Alive::getTimestampOfUpdateEvent(const TimeSortedUpdateEvent f_updateEvent) noexcept(true) { timers::NanoSecondType timestamp{0U}; - if (std::holds_alternative(f_updateEvent)) + if (std::holds_alternative(f_updateEvent)) { - timestamp = std::get(f_updateEvent).timestamp; + timestamp = std::get(f_updateEvent).timestamp; } else if (std::holds_alternative(f_updateEvent)) { diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.hpp index c8b5af4e3b..790c13358d 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive.hpp @@ -139,21 +139,21 @@ class Alive : public ISupervision, timers::NanoSecondType timestamp{UINT64_MAX}; }; - /// @brief Time sorted process state snapshot (activation / deactivation event) - struct ProcessStateSnapshot final + /// @brief Time sorted supervision event snapshot (activation / deactivation event) + struct SupervisionEventSnapshot final { - /// @brief Timestamp of the process state change + /// @brief Timestamp of the supervision event timers::NanoSecondType timestamp{UINT64_MAX}; - /// @brief Process state that triggered this snapshot + /// @brief Supervision event type that triggered this snapshot // cppcheck-suppress unusedStructMember - ifexm::ProcessState::EProcState eProcState{ifexm::ProcessState::EProcState::idle}; + score::lcm::SupervisionEventType eventType{score::lcm::SupervisionEventType::kDeactivation}; }; /// @brief Sync snapshot stores sync timestamp in the time sorting buffer using SyncSnapshot = timers::NanoSecondType; /// @brief Defines one element of time sorted update event - using TimeSortedUpdateEvent = std::variant; + using TimeSortedUpdateEvent = std::variant; /// @brief Enumeration of supervision update events enum class EUpdateEventType : std::uint8_t diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive_UT.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive_UT.cpp index 14a001a5d8..77f9a2854b 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive_UT.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/supervision/Alive_UT.cpp @@ -28,7 +28,6 @@ using namespace testing; using EStatus = score::lcm::saf::supervision::Alive::EStatus; -using EProcState = score::lcm::saf::ifexm::ProcessState::EProcState; namespace { @@ -118,27 +117,19 @@ struct AliveFixture processState.attachObserver(*alive); } - /// Simulate the process reporting kRunning at the given timestamp. + /// Simulate supervision activation (process reached running state). void activateProcess(score::lcm::saf::timers::NanoSecondType timestamp) { processState.setTimestamp(timestamp); - processState.setState(EProcState::running); + processState.setEventType(score::lcm::SupervisionEventType::kActivation); processState.pushData(); } - /// Simulate the process reporting sigterm at the given timestamp. - void sigtermProcess(score::lcm::saf::timers::NanoSecondType timestamp) + /// Simulate supervision deactivation (process terminating). + void deactivateProcess(score::lcm::saf::timers::NanoSecondType timestamp) { processState.setTimestamp(timestamp); - processState.setState(EProcState::sigterm); - processState.pushData(); - } - - /// Simulate the process crashing (off without sigterm) at the given timestamp. - void crashProcess(score::lcm::saf::timers::NanoSecondType timestamp) - { - processState.setTimestamp(timestamp); - processState.setState(EProcState::off); + processState.setEventType(score::lcm::SupervisionEventType::kDeactivation); processState.pushData(); } @@ -260,9 +251,9 @@ TEST_F(AliveSupervisionTest, AliveDebouncesThroughFailedBeforeExpired) EXPECT_EQ(fix.alive->getStatus(), EStatus::kExpired); } -TEST_F(AliveSupervisionTest, DeactivatesOnProcessSigterm) +TEST_F(AliveSupervisionTest, DeactivatesOnSupervisionDeactivation) { - RecordProperty("Description", "Verify that a clean shutdown (sigterm) deactivates the supervision from ok."); + RecordProperty("Description", "Verify that a deactivation event deactivates the supervision from ok."); AliveFixture fix = AliveFixture::Builder{}.build(); EXPECT_CALL(*fix.mockClient, sendRecoveryRequest(_)).Times(0); @@ -271,34 +262,17 @@ TEST_F(AliveSupervisionTest, DeactivatesOnProcessSigterm) fix.alive->evaluate(11U); EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); - fix.sigtermProcess(20U); + fix.deactivateProcess(20U); fix.alive->evaluate(21U); EXPECT_EQ(fix.alive->getStatus(), EStatus::kDeactivated); } -TEST_F(AliveSupervisionTest, DeactivatesOnProcessCrash) -{ - RecordProperty( - "Description", "Verify that a process crash (off without sigterm) also deactivates the supervision."); - AliveFixture fix = AliveFixture::Builder{}.build(); - - EXPECT_CALL(*fix.mockClient, sendRecoveryRequest(_)).Times(0); - - fix.activateProcess(10U); - fix.alive->evaluate(11U); - EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); - - fix.crashProcess(20U); - fix.alive->evaluate(21U); - EXPECT_EQ(fix.alive->getStatus(), EStatus::kDeactivated); -} - -TEST_F(AliveSupervisionTest, ReactivatesAfterCrash) +TEST_F(AliveSupervisionTest, ReactivatesAfterDeactivation) { RecordProperty( "Description", - "Verify that after a crash (off) the supervision can be reactivated when the process" - " reports running again, without any special recovery path."); + "Verify that after a deactivation the supervision can be reactivated when an activation" + " event is received again."); AliveFixture fix = AliveFixture::Builder{}.build(); EXPECT_CALL(*fix.mockClient, sendRecoveryRequest(_)).Times(0); @@ -307,45 +281,15 @@ TEST_F(AliveSupervisionTest, ReactivatesAfterCrash) fix.alive->evaluate(11U); EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); - // Process crashes - fix.crashProcess(20U); + fix.deactivateProcess(20U); fix.alive->evaluate(21U); EXPECT_EQ(fix.alive->getStatus(), EStatus::kDeactivated); - // Process restarts fix.activateProcess(30U); fix.alive->evaluate(31U); EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); } -TEST_F(AliveSupervisionTest, IgnoresIrrelevantProcessStates) -{ - RecordProperty( - "Description", - "Verify that process states other than running/sigterm/off are ignored and do not" - " affect the supervision state."); - AliveFixture fix = AliveFixture::Builder{}.build(); - - EXPECT_CALL(*fix.mockClient, sendRecoveryRequest(_)).Times(0); - - // idle and starting before activation — supervision must stay deactivated - fix.processState.setTimestamp(5U); - fix.processState.setState(EProcState::idle); - fix.processState.pushData(); - - fix.processState.setTimestamp(6U); - fix.processState.setState(EProcState::starting); - fix.processState.pushData(); - - fix.alive->evaluate(7U); - EXPECT_EQ(fix.alive->getStatus(), EStatus::kDeactivated); - - // Normal activation still works after ignored events - fix.activateProcess(10U); - fix.alive->evaluate(11U); - EXPECT_EQ(fix.alive->getStatus(), EStatus::kOk); -} - TEST_F(AliveSupervisionTest, MaxIndicationViolationExpires) { RecordProperty("Description", "Verify that exceeding the maximum allowed heartbeats per cycle leads to failure."); diff --git a/score/launch_manager/src/daemon/src/common/BUILD b/score/launch_manager/src/daemon/src/common/BUILD index 78ae20afb5..81345f6491 100644 --- a/score/launch_manager/src/daemon/src/common/BUILD +++ b/score/launch_manager/src/daemon/src/common/BUILD @@ -98,6 +98,14 @@ cc_library( visibility = ["//score:__subpackages__"], ) +cc_library( + name = "process_state", + hdrs = ["process_state.hpp"], + include_prefix = "score/mw/launch_manager/common", + strip_include_prefix = "/score/launch_manager/src/daemon/src/common", + visibility = ["//score:__subpackages__"], +) + cc_library( name = "process_group_state_id", hdrs = [ diff --git a/score/launch_manager/src/daemon/src/common/process_state.hpp b/score/launch_manager/src/daemon/src/common/process_state.hpp new file mode 100644 index 0000000000..7c8e79cd49 --- /dev/null +++ b/score/launch_manager/src/daemon/src/common/process_state.hpp @@ -0,0 +1,39 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#ifndef SCORE_LCM_PROCESS_STATE_HPP_INCLUDED +#define SCORE_LCM_PROCESS_STATE_HPP_INCLUDED + +#include + +namespace score +{ + +namespace lcm +{ + +/// @brief Represents the state of a modelled process. +enum class ProcessState : std::uint8_t +{ + kIdle = 0, ///< process in idle state. + kStarting = 1, ///< process in starting state. + kRunning = 2, ///< process in running state. + kTerminating = 3, ///< process in terminating state. + kTerminated = 4 ///< process in terminated state. +}; + +} // namespace lcm + +} // namespace score + +#endif // SCORE_LCM_PROCESS_STATE_HPP_INCLUDED diff --git a/score/launch_manager/src/daemon/src/configuration/BUILD b/score/launch_manager/src/daemon/src/configuration/BUILD index ea7787930f..4329824b7a 100644 --- a/score/launch_manager/src/daemon/src/configuration/BUILD +++ b/score/launch_manager/src/daemon/src/configuration/BUILD @@ -135,7 +135,7 @@ cc_library( "//score/launch_manager/src/daemon/src/common:process_group_state_id", "//score/launch_manager/src/daemon/src/osal:num_cores", "//score/launch_manager/src/daemon/src/process_group_manager:iprocess", - "//score/launch_manager/src/daemon/src/process_state_client:posix_process", + "//score/launch_manager/src/daemon/src/common:process_state", ], ) @@ -147,7 +147,7 @@ lm_cc_test( ":configuration_adapter", "//score/launch_manager/src/daemon/src/osal:num_cores", "//score/launch_manager/src/daemon/src/process_group_manager:iprocess", - "//score/launch_manager/src/daemon/src/process_state_client:posix_process", + "//score/launch_manager/src/daemon/src/common:process_state", "@googletest//:gtest_main", "@score_baselibs//score/flatbuffers:flatbufferscpp", ], diff --git a/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp b/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp index 146b0ee50d..00beaf7bc5 100644 --- a/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp +++ b/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp @@ -17,9 +17,9 @@ #include "score/mw/launch_manager/common/constants.hpp" #include "score/mw/launch_manager/common/identifier_hash.hpp" #include "score/mw/launch_manager/common/process_group_state_id.hpp" +#include "score/mw/launch_manager/common/process_state.hpp" #include "score/mw/launch_manager/configuration/config.hpp" #include "score/mw/launch_manager/process_group_manager/iprocess.hpp" -#include "score/mw/launch_manager/process_state_client/posix_process.hpp" #include #include #include diff --git a/score/launch_manager/src/daemon/src/main.cpp b/score/launch_manager/src/daemon/src/main.cpp index d6aaae823c..56630f049f 100644 --- a/score/launch_manager/src/daemon/src/main.cpp +++ b/score/launch_manager/src/daemon/src/main.cpp @@ -21,8 +21,8 @@ #include "score/mw/launch_manager/configuration/flatbuffer_config_loader.hpp" #include "score/mw/launch_manager/process_group_manager/alive_monitor_thread.hpp" #include "score/mw/launch_manager/process_group_manager/process_group_manager.hpp" -#include "score/mw/launch_manager/process_state_client/process_state_notifier.hpp" #include "score/mw/launch_manager/recovery_client/recovery_client.hpp" +#include "score/mw/launch_manager/supervision_control_client/supervision_control_notifier.hpp" #include "score/mw/launch_manager/watchdog/WatchdogFactory.hpp" using namespace std; @@ -157,16 +157,21 @@ int main(int argc, const char* argv[]) } LM_LOG_DEBUG() << "Launch Manager Started !!!!"; std::shared_ptr recoveryClient{std::make_shared()}; - auto process_state_notifier = std::make_unique(); + std::unique_ptr watchdog{ + std::make_unique()}; + auto supervision_control_notifier = std::make_unique(); std::unique_ptr healthMonitor{ std::make_unique( - recoveryClient, process_state_notifier->constructReceiver(), *config_result)}; + recoveryClient, supervision_control_notifier->constructReceiver(), *config_result)}; std::unique_ptr aliveMonitorThread{ std::make_unique(std::move(healthMonitor))}; auto watchdog = score::lcm::watchdog::createWatchdog(); auto process_group_manager = std::make_unique( - std::move(aliveMonitorThread), recoveryClient, std::move(process_state_notifier), std::move(watchdog)); + std::move(aliveMonitorThread), + recoveryClient, + std::move(supervision_control_notifier), + std::move(watchdog)); if (process_group_manager->initialize(*config_result)) { diff --git a/score/launch_manager/src/daemon/src/process_group_manager/BUILD b/score/launch_manager/src/daemon/src/process_group_manager/BUILD index d9dbb62a39..84199230de 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/BUILD +++ b/score/launch_manager/src/daemon/src/process_group_manager/BUILD @@ -82,7 +82,7 @@ cc_library( "//score/launch_manager/src/daemon/src/process_group_manager/details:process_launcher", "//score/launch_manager/src/daemon/src/process_group_manager/details:process_monitor", "//score/launch_manager/src/daemon/src/process_group_manager/details:safe_process_map", - "//score/launch_manager/src/daemon/src/process_state_client:iprocess_state_notifier", + "//score/launch_manager/src/daemon/src/supervision_control_client:isupervision_control_notifier", "//score/launch_manager/src/daemon/src/recovery_client", "//score/launch_manager/src/daemon/src/watchdog:i_watchdog_if", "@score_baselibs//score/language/futurecpp", diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/BUILD b/score/launch_manager/src/daemon/src/process_group_manager/details/BUILD index b055fcb48b..2d34d3375b 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/BUILD +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/BUILD @@ -150,7 +150,7 @@ cc_library( "//score/launch_manager/src/daemon/src/osal:ipc_comms", "//score/launch_manager/src/daemon/src/osal:semaphore", "//score/launch_manager/src/daemon/src/process_group_manager:iprocess", - "//score/launch_manager/src/daemon/src/process_state_client", + "//score/launch_manager/src/daemon/src/supervision_control_client", "@score_baselibs//score/language/futurecpp", ], ) diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp index 8ebe1fa313..bdd3322063 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp @@ -39,7 +39,7 @@ Graph::Graph( std::shared_ptr job_queue, osal::IProcess* process_interface, std::shared_ptr process_map, - IProcessStateNotifier* process_state_notifier, + ISupervisionControlNotifier* supervision_control_notifier, ITransitionResultPublisher* transition_result_receiver) : pg_index_(0U), nodes_(max_num_nodes), @@ -50,7 +50,7 @@ Graph::Graph( job_queue_(job_queue), process_interface_(process_interface), process_map_(process_map), - process_state_notifier_(process_state_notifier), + supervision_control_notifier_(supervision_control_notifier), transition_result_receiver_(transition_result_receiver), last_state_manager_(), last_execution_error_(0U), @@ -105,7 +105,7 @@ void Graph::createProcessInfoNodes(uint32_t num_processes) process_info.processStateId = state; process_info.processGroupStateId = getProcessGroupState(); process_info.systemClockTimestamp = timestamp; - return process_state_notifier_->queuePosixProcess(process_info); + return supervision_control_notifier_->queuePosixProcess(process_info); }; const auto* config = diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.hpp b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.hpp index 2de74d6f40..15ba92b5a0 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.hpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.hpp @@ -36,7 +36,7 @@ #include "score/mw/launch_manager/process_group_manager/details/run_target.hpp" #include "score/mw/launch_manager/process_group_manager/details/transition.hpp" #include "score/mw/launch_manager/process_group_manager/iprocess.hpp" -#include "score/mw/launch_manager/process_state_client/iprocess_state_notifier.hpp" +#include "score/mw/launch_manager/supervision_control_client/isupervision_control_notifier.hpp" #include namespace score @@ -157,7 +157,7 @@ class Graph final std::shared_ptr job_queue, osal::IProcess* process_interface, std::shared_ptr process_map, - IProcessStateNotifier* process_state_notifier, + ISupervisionControlNotifier* supervision_control_notifier, ITransitionResultPublisher* transition_result_receiver); /// @brief Destructor to clean up resources used by the Graph object. @@ -391,7 +391,7 @@ class Graph final std::shared_ptr process_map_; /// @brief Interface to pass process nodes for alive monitor notifications - IProcessStateNotifier* process_state_notifier_; + ISupervisionControlNotifier* supervision_control_notifier_; /// @brief Class to receive information about the initial state transition result ITransitionResultPublisher* transition_result_receiver_; diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp index 2b1de4c88e..720980ead7 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp @@ -32,11 +32,11 @@ class MockProcessMap : public SafeProcessMapInserter MOCK_METHOD(SafeProcessMapReturnType, insertIfNotTerminated, (osal::ProcessID key, IComponent* object), (override)); }; -class MockProcessStateNotifier : public IProcessStateNotifier +class MockProcessStateNotifier : public ISupervisionControlNotifier { public: - MOCK_METHOD(std::unique_ptr, constructReceiver, (), (override)); - MOCK_METHOD(bool, queuePosixProcess, (const score::lcm::PosixProcess& f_posixProcess), (override, noexcept)); + MOCK_METHOD(std::unique_ptr, constructReceiver, (), (override)); + MOCK_METHOD(bool, queueSupervisionEvent, (const score::lcm::SupervisionEvent& f_event), (override, noexcept)); }; class MockTransitionResultPublisher : public ITransitionResultPublisher @@ -53,7 +53,7 @@ class GraphTest : public ::testing::Test RecordProperty("TestType", "interface-test"); RecordProperty("DerivationTechnique", "equivalence-classes"); - ON_CALL(mock_process_state_notifier_, queuePosixProcess).WillByDefault(Return(true)); + ON_CALL(mock_supervision_control_notifier_, queuePosixProcess).WillByDefault(Return(true)); auto procs = SetConfig(); @@ -185,7 +185,7 @@ class GraphTest : public ::testing::Test std::shared_ptr job_queue_ = std::make_shared(); StrictMock process_interface_{}; std::shared_ptr mock_process_map = std::make_shared(); - NiceMock mock_process_state_notifier_{}; + NiceMock mock_supervision_control_notifier_{}; MockTransitionResultPublisher mock_transition_result_publisher_{}; Graph graph_{ 10U, @@ -193,7 +193,7 @@ class GraphTest : public ::testing::Test job_queue_, &process_interface_, mock_process_map, - &mock_process_state_notifier_, + &mock_supervision_control_notifier_, &mock_transition_result_publisher_}; static constexpr std::string_view pg_string{"MainPG"}; diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp index 08c82881b7..b06046bc2a 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp @@ -116,17 +116,24 @@ bool ProcessInfoNode::setState(score::lcm::ProcessState new_state) score::lcm::ProcessState::kIdle != new_state) { // for a reporting process, report a process state change to PHM - // Note the following system call will not fail by design. - // Possible failure modes would be: - // a) CLOCK_MONOTONIC is not supported, but we assert that in all systems it is supported - // b) ×tamp points outside the accessible address space, but it does not + std::optional eventType; + if (new_state == score::lcm::ProcessState::kRunning) + { + eventType = score::lcm::SupervisionEventType::kActivation; + } + else if ( + new_state == score::lcm::ProcessState::kTerminating || new_state == score::lcm::ProcessState::kTerminated) + { + eventType = score::lcm::SupervisionEventType::kDeactivation; + } + timespec timestamp{}; static_cast(clock_gettime(CLOCK_MONOTONIC, ×tamp)); // Note that we ignore the return value. // An error would indicate that PHM is not reading values fast enough from the shared memory; the buffer // over-run should be visible at the PHM side and handled there. If PHM is not responding do we need to handle // this? If PHM terminates state manager will be informed in any case. - static_cast(report_state_(config_->process_id_, new_state, timestamp)); + static_cast(report_state_(config_->process_id_, eventType, timestamp)); } return success; diff --git a/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.cpp b/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.cpp index 0dae2b41c4..6d28fc2199 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.cpp @@ -41,7 +41,7 @@ void ProcessGroupManager::cancel() ProcessGroupManager::ProcessGroupManager( std::unique_ptr alive_monitor_thread, std::shared_ptr recovery_client, - std::unique_ptr process_state_notifier, + std::unique_ptr supervision_control_notifier, std::unique_ptr watchdog) : configuration_(), process_interface_(), @@ -50,7 +50,7 @@ ProcessGroupManager::ProcessGroupManager( worker_jobs_(nullptr), num_process_groups_(0U), process_groups_(), - process_state_notifier_(std::move(process_state_notifier)), + supervision_control_notifier_(std::move(supervision_control_notifier)), alive_monitor_thread_(std::move(alive_monitor_thread)), recovery_client_(recovery_client), watchdog_(std::move(watchdog)) @@ -245,7 +245,7 @@ bool ProcessGroupManager::initializeProcessGroups() worker_jobs_, &process_interface_, process_map_, - process_state_notifier_.get(), + supervision_control_notifier_.get(), this)); } } diff --git a/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.hpp b/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.hpp index 529a17a16d..74aa4ed1a8 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.hpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.hpp @@ -35,8 +35,8 @@ #include "score/mw/launch_manager/process_group_manager/details/safe_process_map.hpp" #include "score/mw/launch_manager/process_group_manager/ialive_monitor_thread.hpp" #include "score/mw/launch_manager/process_group_manager/iprocess.hpp" -#include "score/mw/launch_manager/process_state_client/iprocess_state_notifier.hpp" #include "score/mw/launch_manager/recovery_client/recovery_client.hpp" +#include "score/mw/launch_manager/supervision_control_client/isupervision_control_notifier.hpp" #include "score/mw/launch_manager/watchdog/IWatchdogIf.hpp" namespace score::lcm::internal @@ -71,13 +71,14 @@ class ProcessGroupManager final : public ITransitionResultPublisher /// @param alive_monitor_thread A unique pointer to an IAliveMonitorThread instance for managing health /// monitoring. /// @param recovery_client A shared pointer to an IRecoveryClient instance for handling recovery operations. - /// @param process_state_notifier A unique pointer to an IProcessStateNotifier instance for notifying the Alive - /// Monitor thread of process state changes. - /// @param watchdog A unique pointer to an IWatchdogIf instance serviced during the main loop. Must not be nullptr. + /// @param supervision_control_notifier A unique pointer to an ISupervisionControlNotifier instance for notifying + /// the Alive Monitor thread of process state changes. + /// @param watchdog A unique pointer to an IWatchdogIf instance serviced during the main loop. May be nullptr in + /// legacy configuration where no watchdog is wired. ProcessGroupManager( std::unique_ptr alive_monitor_thread, std::shared_ptr recovery_client, - std::unique_ptr process_state_notifier, + std::unique_ptr supervision_control_notifier, std::unique_ptr watchdog); /// @brief Initializes the process group manager. @@ -145,16 +146,12 @@ class ProcessGroupManager final : public ITransitionResultPublisher /// @return Shared pointer to the MpmcQueue object for ProcessInfoNode jobs. std::shared_ptr getWorkerJobs(); - /// @brief Calls QueuePosixProcess method of psn data member - /// @details Writes via IPC the latest Process State change, so that PHM can be informed about it. - /// the PosixProcess structure should be complete at his moment. That means: - /// ProcessGroupStateId, ProcessModelled Id, current ProcessState, timestamp are known and set. - /// if no more free shared memory, the PosixProcess is not sent. - /// @param[in] f_posixProcess The PosixProcess to be queued - /// @returns True on success, false for failure (corresponding to kCommunicationError). - bool queuePosixProcess(const score::lcm::PosixProcess& f_posixProcess) + /// @brief Control Activation / Deactivation of alive supervisions + /// @param[in] f_event The SupervisionEvent to be queued + /// @returns True on success, false for failure + bool queueSupervisionEvent(const score::lcm::SupervisionEvent& f_event) { - return process_state_notifier_->queuePosixProcess(f_posixProcess); + return supervision_control_notifier_->queueSupervisionEvent(f_event); } /// @brief Cancels processGroupManager main routine as though SIGTERM had been sent @@ -318,7 +315,10 @@ class ProcessGroupManager final : public ITransitionResultPublisher std::shared_ptr machine_process_group_{nullptr}; /// @brief Process state notifier object used to send data to PHM - std::unique_ptr process_state_notifier_; + std::unique_ptr supervision_control_notifier_; + + /// @brief pointer to the configuration for Launch Manager + const OsProcess* launch_manager_config_{nullptr}; std::unique_ptr alive_monitor_thread_; diff --git a/score/launch_manager/src/daemon/src/process_state_client/BUILD b/score/launch_manager/src/daemon/src/process_state_client/BUILD deleted file mode 100644 index 25838e161c..0000000000 --- a/score/launch_manager/src/daemon/src/process_state_client/BUILD +++ /dev/null @@ -1,85 +0,0 @@ -# ******************************************************************************* -# Copyright (c) 2026 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0 -# -# SPDX-License-Identifier: Apache-2.0 -# ******************************************************************************* -load("@rules_cc//cc:defs.bzl", "cc_library") -load("//tests/utils/bazel:unit_test.bzl", "lm_cc_test") - -cc_library( - name = "posix_process", - hdrs = ["posix_process.hpp"], - include_prefix = "score/mw/launch_manager/process_state_client", - strip_include_prefix = "/score/launch_manager/src/daemon/src/process_state_client", - visibility = ["//score:__subpackages__"], - deps = [ - "//score/launch_manager/src/daemon/src/common:identifier_hash", - ], -) - -cc_library( - name = "iprocess_state_receiver", - hdrs = ["iprocess_state_receiver.hpp"], - include_prefix = "score/mw/launch_manager/process_state_client", - strip_include_prefix = "/score/launch_manager/src/daemon/src/process_state_client", - visibility = ["//score:__subpackages__"], - deps = [ - ":posix_process", - "//score/launch_manager:error", - "@score_baselibs//score/result", - ], -) - -cc_library( - name = "iprocess_state_notifier", - hdrs = ["iprocess_state_notifier.hpp"], - include_prefix = "score/mw/launch_manager/process_state_client", - strip_include_prefix = "/score/launch_manager/src/daemon/src/process_state_client", - visibility = ["//score:__subpackages__"], - deps = [ - ":iprocess_state_receiver", - ":posix_process", - ], -) - -cc_library( - name = "process_state_notifier", - srcs = ["process_state_notifier.cpp"], - hdrs = ["process_state_notifier.hpp"], - include_prefix = "score/mw/launch_manager/process_state_client", - strip_include_prefix = "/score/launch_manager/src/daemon/src/process_state_client", - visibility = ["//score:__subpackages__"], - deps = [ - ":iprocess_state_notifier", - "//externals/ipc_dropin", - "//score/launch_manager/src/daemon/src/common:log", - "//score/launch_manager/src/daemon/src/process_state_client/details:process_state_receiver", - ], -) - -cc_library( - name = "process_state_client", - visibility = ["//score:__subpackages__"], - deps = [ - ":process_state_notifier", - "//score/launch_manager/src/daemon/src/process_state_client/details:process_state_receiver", - ], -) - -lm_cc_test( - name = "process_state_client_ut", - srcs = ["process_state_client_ut.cpp"], - tags = ["no-tsan"], - deps = [ - ":process_state_client", - "//score/launch_manager/src/daemon/src/process_state_client/details:process_state_receiver", - "@googletest//:gtest_main", - ], -) diff --git a/score/launch_manager/src/daemon/src/process_state_client/details/process_state_receiver.hpp b/score/launch_manager/src/daemon/src/process_state_client/details/process_state_receiver.hpp deleted file mode 100644 index 58e41d4a5e..0000000000 --- a/score/launch_manager/src/daemon/src/process_state_client/details/process_state_receiver.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -#ifndef PROCESSSTATERECEIVER_HPP_INCLUDED -#define PROCESSSTATERECEIVER_HPP_INCLUDED - -#include "ipc_dropin/ringbuffer.hpp" -#include "score/mw/launch_manager/process_state_client/iprocess_state_receiver.hpp" - -namespace score -{ - -namespace lcm -{ - -using BufferP = std::shared_ptr(score::lcm::BufferConstants::BUFFER_QUEUE_SIZE), - static_cast(score::lcm::BufferConstants::BUFFER_MAXPAYLOAD)>>; - -/// @brief ProcessStateReceiver implementation for handling the information about current state of each Process. -class ProcessStateReceiver final : public IProcessStateReceiver -{ - public: - /// @brief Constructor that creates the ProcessStateReceiver - /// @param ring_buffer Shared pointer to the ring buffer used to receive process state updates from LCM - ProcessStateReceiver(BufferP ring_buffer) noexcept; - - /// @brief Copy constructor that creates the ProcessStateReceiver. It is disabled. - ProcessStateReceiver(const ProcessStateReceiver&) noexcept = delete; - - /// @brief Move constructor that creates the ProcessStateReceiver. It is disabled. - ProcessStateReceiver(ProcessStateReceiver&&) noexcept = delete; - - /// @brief Disable copy-assign another ProcessStateReceiver to this instance. - /// @param other the other instance - /// @returns *this, containing the contents of @a other - ProcessStateReceiver& operator=(const ProcessStateReceiver& other) = delete; - - /// @brief Move operation disabled for this class. - /// @param other the other instance - /// @returns *this, containing the contents of @a other - ProcessStateReceiver& operator=(ProcessStateReceiver&& other) = delete; - - /// @brief Destructor. - ~ProcessStateReceiver() noexcept; - - /// @brief Returns the queued PosixProcess, which changed and PHM has not yet parsed. - /// @returns Returns the queued PosixProcess, which PHM has not yet parsed. - /// "std::nullopt" is returned in case there is no new information. - /// "score::mw::lifecycle::ExecErrc::kGeneralError" is returned in case of any other error. - score::Result> getNextChangedPosixProcess() noexcept override; - - private: - /// @brief ipc_dropin::RingBuffer through which we retrieve process state updates from LCM - BufferP ring_buffer_{}; -}; - -} // namespace lcm - -} // namespace score - -#endif // PROCESSSTATERECEIVER_HPP_INCLUDED diff --git a/score/launch_manager/src/daemon/src/process_state_client/iprocess_state_notifier.hpp b/score/launch_manager/src/daemon/src/process_state_client/iprocess_state_notifier.hpp deleted file mode 100644 index 07e79cece5..0000000000 --- a/score/launch_manager/src/daemon/src/process_state_client/iprocess_state_notifier.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2026 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#ifndef IPROCESSSTATE_NOTIFIER_HPP_INCLUDED -#define IPROCESSSTATE_NOTIFIER_HPP_INCLUDED - -#include "score/mw/launch_manager/process_state_client/iprocess_state_receiver.hpp" -#include "score/mw/launch_manager/process_state_client/posix_process.hpp" - -namespace score -{ - -namespace lcm -{ - -/// -/// @brief IProcessStateNotifier interface for handling the information about each Process current state. -/// Launch Manager (LCM) shall use this interface in order to properly store -/// information about the current state from the posix processes running in the scope of an Adaptive Machine. -/// Each posix process state change is stored by Launch Manager (LCM) and can be read by HM. -/// - -class IProcessStateNotifier -{ - public: - /// @brief Destructor. - virtual ~IProcessStateNotifier() noexcept = default; - - /// @brief Construct and return the Process State Receiver instance used to receive process state changes. - /// @return Process State Receiver instance - virtual std::unique_ptr constructReceiver() = 0; - - /// @brief Writes via IPC the latests Process State change, so that PHM can be informed about it. - /// @details the PosixProcess structure should be complete at his moment. That means: - /// ProcessGroupStateId, ProcessModelled Id, current ProcessState, timestamp are known and set. - /// if no more free shared memory, the PosixProcess is not sent. - /// @param[in] f_posixProcess The PosixProcess to be queued - /// @returns True on success, false for failure (corresponding to kCommunicationError). - virtual bool queuePosixProcess(const score::lcm::PosixProcess& f_posixProcess) noexcept = 0; -}; - -} // namespace lcm - -} // namespace score - -#endif diff --git a/score/launch_manager/src/daemon/src/process_state_client/iprocess_state_receiver.hpp b/score/launch_manager/src/daemon/src/process_state_client/iprocess_state_receiver.hpp deleted file mode 100644 index a88c7ab8b1..0000000000 --- a/score/launch_manager/src/daemon/src/process_state_client/iprocess_state_receiver.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2026 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#ifndef IPROCESSSTATERECEIVER_HPP_INCLUDED -#define IPROCESSSTATERECEIVER_HPP_INCLUDED - -#include "score/mw/lifecycle/execution_error.h" -#include "score/result/result.h" -#include -#include - -#include "score/mw/launch_manager/process_state_client/posix_process.hpp" - -namespace score -{ - -namespace lcm -{ - -/// @brief IProcessStateReceiver interface for handling the information about each Process current state. -/// Alive Monitor (AM) shall use this interface in order to properly receive -/// information about the current state from the posix processes running in the scope of an Adaptive Machine. -/// Each posix process state change is sent by Launch Manager (LCM) and can be read by AM. - -class IProcessStateReceiver -{ - public: - virtual ~IProcessStateReceiver() noexcept = default; - - /// @brief Returns a queued PosixProcess that has not yet been parsed. - /// @returns Result containing PosixProcess in case of success, or ExecError in case of failure. - virtual score::Result> getNextChangedPosixProcess() noexcept = 0; -}; - -} // namespace lcm - -} // namespace score - -#endif diff --git a/score/launch_manager/src/daemon/src/process_state_client/posix_process.hpp b/score/launch_manager/src/daemon/src/process_state_client/posix_process.hpp deleted file mode 100644 index cb775c00fc..0000000000 --- a/score/launch_manager/src/daemon/src/process_state_client/posix_process.hpp +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -#ifndef POSIXPROCESS_HPP_INCLUDED -#define POSIXPROCESS_HPP_INCLUDED - -#include "score/mw/launch_manager/common/identifier_hash.hpp" -#include -#include // for definition of "timespec" - -namespace score -{ - -namespace lcm -{ - -/// @brief Represents the state of a modelled process. -enum class ProcessState : std::uint8_t -{ - kIdle = 0, ///< process in idle state. - kStarting = 1, ///< process in starting state. - kRunning = 2, ///< process in running state. - kTerminating = 3, ///< process in terminating state. - kTerminated = 4, ///< process in terminated state. - kFailed = 5, ///< process failed to start -}; - -/// @brief Structure containing the Process's current state, its mapped ProcessGroupState and the timestamp when the -/// process state changed. -/// @details This structure will be probably populated in steps, since some Software Components know about the current -/// ProcessGroupStateId -/// and Process Modelled Id (like ProcessGroupManager); meanwhile others know about the process state changes -/// from a specific posix process (like application launcher). The timestamp shall show when the process state -/// changed. Finally the ProcessStateReceiver knows if the PosixProcess was already read by PHM or not. -/// - -// RULECHECKER_comment(1, 1, check_incomplete_data_member_construction, "wi 45913 - This struct is POD, which doesn't -// have user-declared constructor. The rule doesn’t apply.", false) -struct PosixProcess -{ - /// @brief Stores the Modelled Process ID as IdentifierHash. - /// @details This ID is assigned by using a hash algorithm on the string of the path. - /// - score::lcm::IdentifierHash id; - - /// @brief Stores the current ProcessState of the posix process. - /// @details This state is assigned by the Launch Manager whenever the posix process changes it current state. - /// i.e., kStarting, kRunning, kTerminating, kTerminated - ProcessState processStateId; - - /// @brief Stores the ProcessGroupState ID in which the Process is active as IdentifierHash. - /// @details This ID is assigned by using a hash algorithm on the string of the path. - score::lcm::IdentifierHash processGroupStateId; - - /// @brief Stores the timestamp based on the system clock when storing the new change of this posix process. - /// @details the timestamp is stored as timespec, since it can deliver precision in nanoseconds. - timespec systemClockTimestamp; -}; - -enum class BufferConstants : size_t -{ - BUFFER_MAXPAYLOAD = sizeof(PosixProcess), ///< Ringbuffer max payload size - // (PROCESS_MAX number (1024) * Transition pattern (4, STARTING/RUNNING/TERMINATING/TERMINATED) - BUFFER_QUEUE_SIZE = 4096UL // Ringbuffer queue size -}; - -} // namespace lcm - -} // namespace score - -#endif // POSIXPROCESS_HPP_INCLUDED diff --git a/score/launch_manager/src/daemon/src/process_state_client/process_state_client_ut.cpp b/score/launch_manager/src/daemon/src/process_state_client/process_state_client_ut.cpp deleted file mode 100644 index 99710182bf..0000000000 --- a/score/launch_manager/src/daemon/src/process_state_client/process_state_client_ut.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2026 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#include "score/mw/launch_manager/process_state_client/details/process_state_receiver.hpp" -#include "score/mw/launch_manager/process_state_client/process_state_notifier.hpp" -#include -#include - -using namespace testing; -using namespace score::lcm; - -using score::lcm::ProcessStateReceiver; -using score::lcm::internal::ProcessStateNotifier; - -class ProcessStateClient_UT : public ::testing::Test -{ - protected: - void SetUp() override - { - RecordProperty("TestType", "interface-test"); - RecordProperty("DerivationTechnique", "explorative-testing "); - notifier_ = std::make_unique(); - receiver_ = notifier_->constructReceiver(); - } - void TearDown() override - { - receiver_.reset(); - notifier_.reset(); - } - std::unique_ptr notifier_; - std::unique_ptr receiver_; -}; - -TEST_F(ProcessStateClient_UT, ProcessStateClient_ConstructReceiver_Succeeds) -{ - RecordProperty( - "Description", - "This test verifies that the ProcessStateNotifier can successfully construct a ProcessStateReceiver instance."); - ASSERT_NE(notifier_, nullptr); - ASSERT_NE(receiver_, nullptr); -} - -TEST_F(ProcessStateClient_UT, ProcessStateClient_QueueOneProcess_Succeeds) -{ - RecordProperty( - "Description", - "This test verifies that a single PosixProcess can be successfully queued using the " - "ProcessStateNotifier and retrieved using the ProcessStateReceiver."); - PosixProcess process1{ - .id = score::lcm::IdentifierHash("Process1"), - .processStateId = score::lcm::ProcessState::kRunning, - .processGroupStateId = score::lcm::IdentifierHash("PGState1"), - .systemClockTimestamp = {}, - }; - - // Queue one process - bool queued = notifier_->queuePosixProcess(process1); - ASSERT_TRUE(queued); - - // Retrieve the queued process via the receiver - auto result = receiver_->getNextChangedPosixProcess(); - ASSERT_TRUE(result.has_value()); // Result contains Optional value - ASSERT_TRUE(result->has_value()); // Optional contains PosixProcess - EXPECT_EQ(result->value().id, process1.id); - EXPECT_EQ(result->value().processStateId, process1.processStateId); - EXPECT_EQ(result->value().processGroupStateId, process1.processGroupStateId); - - // Ensure no more processes are queued - auto no_more = receiver_->getNextChangedPosixProcess(); - ASSERT_TRUE(no_more.has_value()); // Result contains Optional value - ASSERT_FALSE(no_more->has_value()); // Optional is empty -} - -TEST_F(ProcessStateClient_UT, ProcessStateClient_QueueMaxNumberOfProcesses_Succeeds) -{ - RecordProperty( - "Description", - "This test verifies that the ProcessStateNotifier can successfully queue the maximum number of PosixProcess " - "instances defined by the buffer size, and that they can be retrieved using the ProcessStateReceiver."); - // Queue maximum number of processes - for (size_t i = 0; i < static_cast(BufferConstants::BUFFER_QUEUE_SIZE); ++i) - { - PosixProcess process{ - .id = score::lcm::IdentifierHash("Process" + std::to_string(i)), - .processStateId = score::lcm::ProcessState::kRunning, - .processGroupStateId = score::lcm::IdentifierHash("PGState" + std::to_string(i)), - .systemClockTimestamp = {}, - }; - bool queued = notifier_->queuePosixProcess(process); - ASSERT_TRUE(queued) << "Failed to queue process at index " << i; - } - - // Retrieve and verify all queued processes - for (size_t i = 0; i < static_cast(BufferConstants::BUFFER_QUEUE_SIZE); ++i) - { - auto result = receiver_->getNextChangedPosixProcess(); - ASSERT_TRUE(result.has_value()); - ASSERT_TRUE(result->has_value()); - EXPECT_EQ(result->value().id, score::lcm::IdentifierHash("Process" + std::to_string(i))); - } - - // Ensure no more processes are queued - auto no_more = receiver_->getNextChangedPosixProcess(); - ASSERT_TRUE(no_more.has_value()); - ASSERT_FALSE(no_more->has_value()); -} - -TEST_F(ProcessStateClient_UT, ProcessStateClient_QueueOneProcessTooMany_Fails) -{ - RecordProperty( - "Description", - "This test verifies that attempting to queue a PosixProcess when the buffer is already at maximum capacity " - "results in a failure, and that no additional processes can be retrieved from the receiver."); - PosixProcess process1{ - .id = score::lcm::IdentifierHash("Process1"), - .processStateId = score::lcm::ProcessState::kRunning, - .processGroupStateId = score::lcm::IdentifierHash("PGState1"), - .systemClockTimestamp = {}, - }; - - // Fill the buffer to capacity - for (size_t i = 0; i < static_cast(BufferConstants::BUFFER_QUEUE_SIZE); ++i) - { - PosixProcess proc{ - .id = score::lcm::IdentifierHash("Process" + std::to_string(i)), - .processStateId = score::lcm::ProcessState::kRunning, - .processGroupStateId = score::lcm::IdentifierHash("PGState" + std::to_string(i)), - .systemClockTimestamp = {}, - }; - bool queued = notifier_->queuePosixProcess(proc); - ASSERT_TRUE(queued) << "Failed to queue process at index " << i; - } - - // Attempt to queue one more process - bool queued = notifier_->queuePosixProcess(process1); - ASSERT_FALSE(queued) << "Expected queuing to fail due to full buffer"; - - // Ensure that no processes can be retrieved - auto result = receiver_->getNextChangedPosixProcess(); - ASSERT_FALSE(result.has_value()) << "Expected no processes to be retrievable"; - EXPECT_EQ(result.error(), score::mw::lifecycle::ExecErrc::kCommunicationError); -} diff --git a/score/launch_manager/src/daemon/src/process_state_client/process_state_notifier.hpp b/score/launch_manager/src/daemon/src/process_state_client/process_state_notifier.hpp deleted file mode 100644 index f87614cade..0000000000 --- a/score/launch_manager/src/daemon/src/process_state_client/process_state_notifier.hpp +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -#ifndef PROCESSSTATE_NOTIFIER_HPP_INCLUDED -#define PROCESSSTATE_NOTIFIER_HPP_INCLUDED - -#include "ipc_dropin/ringbuffer.hpp" -#include "score/mw/launch_manager/process_state_client/iprocess_state_notifier.hpp" - -namespace score -{ - -namespace lcm -{ - -namespace internal -{ - -/// -/// @brief ProcessStateNotifier implementation for handling the information about each Process current state. -/// Launch Manager (LCM) shall use this implementation in order to properly store -/// information about the current state from the posix processes running in the scope of an Adaptive Machine. -/// Each posix process state change is stored by Launch Manager (LCM) and can be read by PHM. -/// -class ProcessStateNotifier final : public IProcessStateNotifier -{ - public: - /// @brief Constructor that creates the ProcessStateNotifier. - /// @details LCM shall create an instance of this class to write the process state changes via the provided API. - ProcessStateNotifier() noexcept; - - /// @brief Copy constructor that creates the ProcessStateNotifier. - ProcessStateNotifier(const ProcessStateNotifier&) noexcept = delete; - - /// @brief Move constructor that creates the ProcessStateNotifier. - ProcessStateNotifier(ProcessStateNotifier&&) noexcept = delete; - - /// @brief Copy-assign another ProcessStateNotifier to this instance. - /// @param other the other instance - /// @returns *this, containing the contents of @a other - ProcessStateNotifier& operator=(const ProcessStateNotifier& other) = delete; - - /// @brief Move operation disabled for this class. - /// @param other the other instance - /// @returns *this, containing the contents of @a other - ProcessStateNotifier& operator=(ProcessStateNotifier&& other) = delete; - - /// @brief Destructor. - ~ProcessStateNotifier() noexcept; - - /// @brief Construct and return the Process State Receiver instance used to receive process state changes. - /// @return Process State Receiver instance - std::unique_ptr constructReceiver() override; - - /// @brief Writes via IPC the latests Process State change, so that PHM can be informed about it. - /// @details the PosixProcess structure should be complete at his moment. That means: - /// ProcessGroupStateId, ProcessModelled Id, current ProcessState, timestamp are known and set. - /// if no more free shared memory, the PosixProcess is not sent. - /// @param[in] f_posixProcess The PosixProcess to be queued - /// @returns True on success, false for failure (corresponding to kCommunicationError). - bool queuePosixProcess(const score::lcm::PosixProcess& f_posixProcess) noexcept override; - - private: - /// @brief ipc_dropin::RingBuffer through which we retrieve process state updates from LCM - std::shared_ptr(score::lcm::BufferConstants::BUFFER_QUEUE_SIZE), - static_cast(score::lcm::BufferConstants::BUFFER_MAXPAYLOAD)>> - ring_buffer_{}; -}; - -} // namespace internal - -} // namespace lcm - -} // namespace score -#endif diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/BUILD b/score/launch_manager/src/daemon/src/supervision_control_client/BUILD new file mode 100644 index 0000000000..9bdaf78ca4 --- /dev/null +++ b/score/launch_manager/src/daemon/src/supervision_control_client/BUILD @@ -0,0 +1,83 @@ +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") + +cc_library( + name = "supervision_event", + hdrs = ["supervision_event.hpp"], + include_prefix = "score/mw/launch_manager/supervision_control_client", + strip_include_prefix = "/score/launch_manager/src/daemon/src/supervision_control_client", + visibility = ["//score:__subpackages__"], + deps = [ + "//score/launch_manager/src/daemon/src/common:identifier_hash", + ], +) + +cc_library( + name = "isupervision_control_receiver", + hdrs = ["isupervision_control_receiver.hpp"], + include_prefix = "score/mw/launch_manager/supervision_control_client", + strip_include_prefix = "/score/launch_manager/src/daemon/src/supervision_control_client", + visibility = ["//score:__subpackages__"], + deps = [ + ":supervision_event", + "//score/launch_manager:error", + "@score_baselibs//score/result", + ], +) + +cc_library( + name = "isupervision_control_notifier", + hdrs = ["isupervision_control_notifier.hpp"], + include_prefix = "score/mw/launch_manager/supervision_control_client", + strip_include_prefix = "/score/launch_manager/src/daemon/src/supervision_control_client", + visibility = ["//score:__subpackages__"], + deps = [ + ":isupervision_control_receiver", + ":supervision_event", + ], +) + +cc_library( + name = "supervision_control_notifier", + srcs = ["supervision_control_notifier.cpp"], + hdrs = ["supervision_control_notifier.hpp"], + include_prefix = "score/mw/launch_manager/supervision_control_client", + strip_include_prefix = "/score/launch_manager/src/daemon/src/supervision_control_client", + visibility = ["//score:__subpackages__"], + deps = [ + ":isupervision_control_notifier", + "//externals/ipc_dropin", + "//score/launch_manager/src/daemon/src/common:log", + "//score/launch_manager/src/daemon/src/supervision_control_client/details:supervision_control_receiver", + ], +) + +cc_library( + name = "supervision_control_client", + visibility = ["//score:__subpackages__"], + deps = [ + ":supervision_control_notifier", + "//score/launch_manager/src/daemon/src/supervision_control_client/details:supervision_control_receiver", + ], +) + +cc_test( + name = "supervision_control_client_ut", + srcs = ["supervision_control_client_ut.cpp"], + deps = [ + ":supervision_control_client", + "//score/launch_manager/src/daemon/src/supervision_control_client/details:supervision_control_receiver", + "@googletest//:gtest_main", + ], +) diff --git a/score/launch_manager/src/daemon/src/process_state_client/details/BUILD b/score/launch_manager/src/daemon/src/supervision_control_client/details/BUILD similarity index 63% rename from score/launch_manager/src/daemon/src/process_state_client/details/BUILD rename to score/launch_manager/src/daemon/src/supervision_control_client/details/BUILD index b002d06905..97bd6d036e 100644 --- a/score/launch_manager/src/daemon/src/process_state_client/details/BUILD +++ b/score/launch_manager/src/daemon/src/supervision_control_client/details/BUILD @@ -13,15 +13,15 @@ load("@rules_cc//cc:defs.bzl", "cc_library") cc_library( - name = "process_state_receiver", - srcs = ["process_state_receiver.cpp"], - hdrs = ["process_state_receiver.hpp"], - include_prefix = "score/mw/launch_manager/process_state_client/details", - strip_include_prefix = "/score/launch_manager/src/daemon/src/process_state_client/details", - visibility = ["//score/launch_manager/src/daemon/src/process_state_client:__pkg__"], + name = "supervision_control_receiver", + srcs = ["supervision_control_receiver.cpp"], + hdrs = ["supervision_control_receiver.hpp"], + include_prefix = "score/mw/launch_manager/supervision_control_client/details", + strip_include_prefix = "/score/launch_manager/src/daemon/src/supervision_control_client/details", + visibility = ["//score/launch_manager/src/daemon/src/supervision_control_client:__pkg__"], deps = [ "//externals/ipc_dropin", "//score/launch_manager/src/daemon/src/common:log", - "//score/launch_manager/src/daemon/src/process_state_client:iprocess_state_receiver", + "//score/launch_manager/src/daemon/src/supervision_control_client:isupervision_control_receiver", ], ) diff --git a/score/launch_manager/src/daemon/src/process_state_client/details/process_state_receiver.cpp b/score/launch_manager/src/daemon/src/supervision_control_client/details/supervision_control_receiver.cpp similarity index 55% rename from score/launch_manager/src/daemon/src/process_state_client/details/process_state_receiver.cpp rename to score/launch_manager/src/daemon/src/supervision_control_client/details/supervision_control_receiver.cpp index 6009aac35d..91a25a994a 100644 --- a/score/launch_manager/src/daemon/src/process_state_client/details/process_state_receiver.cpp +++ b/score/launch_manager/src/daemon/src/supervision_control_client/details/supervision_control_receiver.cpp @@ -11,7 +11,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -#include "score/mw/launch_manager/process_state_client/details/process_state_receiver.hpp" +#include "score/mw/launch_manager/supervision_control_client/details/supervision_control_receiver.hpp" #include "score/mw/launch_manager/common/log.hpp" namespace score @@ -19,38 +19,38 @@ namespace score namespace lcm { -ProcessStateReceiver::ProcessStateReceiver(BufferP ring_buffer) noexcept : ring_buffer_(ring_buffer) +SupervisionControlReceiver::SupervisionControlReceiver(BufferP ring_buffer) noexcept : ring_buffer_(ring_buffer) { } -ProcessStateReceiver::~ProcessStateReceiver() noexcept +SupervisionControlReceiver::~SupervisionControlReceiver() noexcept { } -score::Result> ProcessStateReceiver::getNextChangedPosixProcess() noexcept +score::Result> SupervisionControlReceiver::getNextSupervisionEvent() noexcept { - score::lcm::PosixProcess changedProcess; + score::lcm::SupervisionEvent event; if (ring_buffer_->getOverflowFlag()) { - LM_LOG_ERROR() << "ProcessStateReceiver::getNextChangedPosixProcess: Overflow occurred, " + LM_LOG_ERROR() << "SupervisionControlReceiver::getNextSupervisionEvent: Overflow occurred, " "will be reported as kCommunicationError"; - return score::Result>{ + return score::Result>{ score::MakeUnexpected(score::mw::lifecycle::ExecErrc::kCommunicationError)}; } if (ring_buffer_->empty()) { - return score::Result>{std::nullopt}; + return score::Result>{std::nullopt}; } - auto res = ring_buffer_->tryDequeue(changedProcess); + auto res = ring_buffer_->tryDequeue(event); if (res) { - return score::Result>{changedProcess}; + return score::Result>{event}; } else { - return score::Result>{ + return score::Result>{ score::MakeUnexpected(score::mw::lifecycle::ExecErrc::kGeneralError)}; } } diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/details/supervision_control_receiver.hpp b/score/launch_manager/src/daemon/src/supervision_control_client/details/supervision_control_receiver.hpp new file mode 100644 index 0000000000..3693f408a5 --- /dev/null +++ b/score/launch_manager/src/daemon/src/supervision_control_client/details/supervision_control_receiver.hpp @@ -0,0 +1,68 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#ifndef SUPERVISION_CONTROL_RECEIVER_HPP_INCLUDED +#define SUPERVISION_CONTROL_RECEIVER_HPP_INCLUDED + +#include "ipc_dropin/ringbuffer.hpp" +#include "score/mw/launch_manager/supervision_control_client/isupervision_control_receiver.hpp" + +namespace score +{ + +namespace lcm +{ + +using BufferP = std::shared_ptr(score::lcm::BufferConstants::BUFFER_QUEUE_SIZE), + static_cast(score::lcm::BufferConstants::BUFFER_MAXPAYLOAD)>>; + +/// @brief SupervisionControlReceiver implementation for receiving supervision events from the Launch Manager. +class SupervisionControlReceiver final : public ISupervisionControlReceiver +{ + public: + /// @brief Constructor that creates the SupervisionControlReceiver + /// @param ring_buffer Shared pointer to the ring buffer used to receive supervision events + SupervisionControlReceiver(BufferP ring_buffer) noexcept; + + /// @brief Copy constructor is disabled. + SupervisionControlReceiver(const SupervisionControlReceiver&) noexcept = delete; + + /// @brief Move constructor is disabled. + SupervisionControlReceiver(SupervisionControlReceiver&&) noexcept = delete; + + /// @brief Copy-assign is disabled. + SupervisionControlReceiver& operator=(const SupervisionControlReceiver& other) = delete; + + /// @brief Move-assign is disabled. + SupervisionControlReceiver& operator=(SupervisionControlReceiver&& other) = delete; + + /// @brief Destructor. + ~SupervisionControlReceiver() noexcept; + + /// @brief Returns the queued SupervisionEvent, which the alive monitor has not yet parsed. + /// @returns Returns the queued SupervisionEvent. + /// "std::nullopt" is returned in case there is no new information. + /// "score::mw::lifecycle::ExecErrc::kGeneralError" is returned in case of any other error. + score::Result> getNextSupervisionEvent() noexcept override; + + private: + /// @brief Ring buffer through which supervision events are received from the Launch Manager + BufferP ring_buffer_{}; +}; + +} // namespace lcm + +} // namespace score + +#endif // SUPERVISION_CONTROL_RECEIVER_HPP_INCLUDED diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/isupervision_control_notifier.hpp b/score/launch_manager/src/daemon/src/supervision_control_client/isupervision_control_notifier.hpp new file mode 100644 index 0000000000..5391e65fbf --- /dev/null +++ b/score/launch_manager/src/daemon/src/supervision_control_client/isupervision_control_notifier.hpp @@ -0,0 +1,48 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef ISUPERVISION_CONTROL_NOTIFIER_HPP_INCLUDED +#define ISUPERVISION_CONTROL_NOTIFIER_HPP_INCLUDED + +#include "score/mw/launch_manager/supervision_control_client/isupervision_control_receiver.hpp" +#include "score/mw/launch_manager/supervision_control_client/supervision_event.hpp" + +namespace score +{ + +namespace lcm +{ + +/// @brief ISupervisionControlNotifier interface for forwarding supervision events to the alive monitor. +/// The Launch Manager uses this interface to notify the alive monitor whenever a supervised +/// process reaches running state (activation) or starts terminating (deactivation). +class ISupervisionControlNotifier +{ + public: + /// @brief Destructor. + virtual ~ISupervisionControlNotifier() noexcept = default; + + /// @brief Construct and return the receiver instance used to receive supervision events. + /// @return Supervision control receiver instance + virtual std::unique_ptr constructReceiver() = 0; + + /// @brief Writes via IPC the latest supervision event, so that the alive monitor can be informed about it. + /// @param[in] f_event The SupervisionEvent to be queued + /// @returns True on success, false for failure + virtual bool queueSupervisionEvent(const score::lcm::SupervisionEvent& f_event) noexcept = 0; +}; + +} // namespace lcm + +} // namespace score + +#endif diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/isupervision_control_receiver.hpp b/score/launch_manager/src/daemon/src/supervision_control_client/isupervision_control_receiver.hpp new file mode 100644 index 0000000000..4efa90b7fa --- /dev/null +++ b/score/launch_manager/src/daemon/src/supervision_control_client/isupervision_control_receiver.hpp @@ -0,0 +1,46 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef ISUPERVISION_CONTROL_RECEIVER_HPP_INCLUDED +#define ISUPERVISION_CONTROL_RECEIVER_HPP_INCLUDED + +#include "score/mw/lifecycle/execution_error.h" +#include "score/result/result.h" +#include +#include + +#include "score/mw/launch_manager/supervision_control_client/supervision_event.hpp" + +namespace score +{ + +namespace lcm +{ + +/// @brief ISupervisionControlReceiver interface for receiving supervision events. +/// The alive monitor uses this interface to receive supervision events (activation/deactivation) +/// forwarded by the Launch Manager. +class ISupervisionControlReceiver +{ + public: + virtual ~ISupervisionControlReceiver() noexcept = default; + + /// @brief Returns a queued SupervisionEvent that has not yet been parsed. + /// @returns Result containing SupervisionEvent in case of success, or ExecError in case of failure. + virtual score::Result> getNextSupervisionEvent() noexcept = 0; +}; + +} // namespace lcm + +} // namespace score + +#endif diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp new file mode 100644 index 0000000000..4cdb56006b --- /dev/null +++ b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp @@ -0,0 +1,135 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/launch_manager/supervision_control_client/details/supervision_control_receiver.hpp" +#include "score/mw/launch_manager/supervision_control_client/supervision_control_notifier.hpp" +#include +#include + +using namespace testing; +using namespace score::lcm; + +using score::lcm::SupervisionControlReceiver; +using score::lcm::internal::SupervisionControlNotifier; + +class SupervisionControlClient_UT : public ::testing::Test +{ + protected: + void SetUp() override + { + RecordProperty("TestType", "interface-test"); + RecordProperty("DerivationTechnique", "explorative-testing "); + notifier_ = std::make_unique(); + receiver_ = notifier_->constructReceiver(); + } + void TearDown() override + { + receiver_.reset(); + notifier_.reset(); + } + std::unique_ptr notifier_; + std::unique_ptr receiver_; +}; + +TEST_F(SupervisionControlClient_UT, SupervisionControlClient_ConstructReceiver_Succeeds) +{ + RecordProperty( + "Description", + "This test verifies that the SupervisionControlNotifier can successfully construct a " + "SupervisionControlReceiver instance."); + ASSERT_NE(notifier_, nullptr); + ASSERT_NE(receiver_, nullptr); +} + +TEST_F(SupervisionControlClient_UT, SupervisionControlClient_QueueOneEvent_Succeeds) +{ + RecordProperty( + "Description", + "This test verifies that a single SupervisionEvent can be successfully queued using the " + "SupervisionControlNotifier and retrieved using the SupervisionControlReceiver."); + SupervisionEvent event1{ + .id = score::lcm::IdentifierHash("Process1"), + .eventType = score::lcm::SupervisionEventType::kActivation, + }; + + bool queued = notifier_->queueSupervisionEvent(event1); + ASSERT_TRUE(queued); + + auto result = receiver_->getNextSupervisionEvent(); + ASSERT_TRUE(result.has_value()); + ASSERT_TRUE(result->has_value()); + EXPECT_EQ(result->value().id, event1.id); + EXPECT_EQ(result->value().eventType, event1.eventType); + + auto no_more = receiver_->getNextSupervisionEvent(); + ASSERT_TRUE(no_more.has_value()); + ASSERT_FALSE(no_more->has_value()); +} + +TEST_F(SupervisionControlClient_UT, SupervisionControlClient_QueueMaxNumberOfEvents_Succeeds) +{ + RecordProperty( + "Description", + "This test verifies that the SupervisionControlNotifier can successfully queue the maximum number of " + "SupervisionEvent " + "instances defined by the buffer size, and that they can be retrieved using the SupervisionControlReceiver."); + for (size_t i = 0; i < static_cast(BufferConstants::BUFFER_QUEUE_SIZE); ++i) + { + SupervisionEvent event{ + .id = score::lcm::IdentifierHash("Process" + std::to_string(i)), + .eventType = score::lcm::SupervisionEventType::kActivation, + }; + bool queued = notifier_->queueSupervisionEvent(event); + ASSERT_TRUE(queued) << "Failed to queue event at index " << i; + } + + for (size_t i = 0; i < static_cast(BufferConstants::BUFFER_QUEUE_SIZE); ++i) + { + auto result = receiver_->getNextSupervisionEvent(); + ASSERT_TRUE(result.has_value()); + ASSERT_TRUE(result->has_value()); + EXPECT_EQ(result->value().id, score::lcm::IdentifierHash("Process" + std::to_string(i))); + } + + auto no_more = receiver_->getNextSupervisionEvent(); + ASSERT_TRUE(no_more.has_value()); + ASSERT_FALSE(no_more->has_value()); +} + +TEST_F(SupervisionControlClient_UT, SupervisionControlClient_QueueOneEventTooMany_Fails) +{ + RecordProperty( + "Description", + "This test verifies that attempting to queue a SupervisionEvent when the buffer is already at maximum capacity " + "results in a failure, and that no additional events can be retrieved from the receiver."); + SupervisionEvent event1{ + .id = score::lcm::IdentifierHash("Process1"), + .eventType = score::lcm::SupervisionEventType::kActivation, + }; + + for (size_t i = 0; i < static_cast(BufferConstants::BUFFER_QUEUE_SIZE); ++i) + { + SupervisionEvent event{ + .id = score::lcm::IdentifierHash("Process" + std::to_string(i)), + .eventType = score::lcm::SupervisionEventType::kActivation, + }; + bool queued = notifier_->queueSupervisionEvent(event); + ASSERT_TRUE(queued) << "Failed to queue event at index " << i; + } + + bool queued = notifier_->queueSupervisionEvent(event1); + ASSERT_FALSE(queued) << "Expected queuing to fail due to full buffer"; + + auto result = receiver_->getNextSupervisionEvent(); + ASSERT_FALSE(result.has_value()) << "Expected no events to be retrievable"; + EXPECT_EQ(result.error(), score::mw::lifecycle::ExecErrc::kCommunicationError); +} diff --git a/score/launch_manager/src/daemon/src/process_state_client/process_state_notifier.cpp b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.cpp similarity index 60% rename from score/launch_manager/src/daemon/src/process_state_client/process_state_notifier.cpp rename to score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.cpp index 3e83fc2996..6b432cb6b9 100644 --- a/score/launch_manager/src/daemon/src/process_state_client/process_state_notifier.cpp +++ b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.cpp @@ -11,9 +11,9 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -#include "score/mw/launch_manager/process_state_client/process_state_notifier.hpp" +#include "score/mw/launch_manager/supervision_control_client/supervision_control_notifier.hpp" #include "score/mw/launch_manager/common/log.hpp" -#include "score/mw/launch_manager/process_state_client/details/process_state_receiver.hpp" +#include "score/mw/launch_manager/supervision_control_client/details/supervision_control_receiver.hpp" namespace score { @@ -22,7 +22,7 @@ namespace lcm namespace internal { -ProcessStateNotifier::ProcessStateNotifier() noexcept +SupervisionControlNotifier::SupervisionControlNotifier() noexcept { ring_buffer_ = std::make_shared(score::lcm::BufferConstants::BUFFER_QUEUE_SIZE), @@ -31,28 +31,28 @@ ProcessStateNotifier::ProcessStateNotifier() noexcept ring_buffer_->initialize(); } -ProcessStateNotifier::~ProcessStateNotifier() noexcept +SupervisionControlNotifier::~SupervisionControlNotifier() noexcept { } -bool ProcessStateNotifier::queuePosixProcess(const score::lcm::PosixProcess& f_posixProcess) noexcept +bool SupervisionControlNotifier::queueSupervisionEvent(const score::lcm::SupervisionEvent& f_event) noexcept { bool ret = true; - if (ring_buffer_->tryEnqueue(f_posixProcess)) + if (ring_buffer_->tryEnqueue(f_event)) { // nothing } else { - LM_LOG_ERROR() << "Failed to queue posix process"; + LM_LOG_ERROR() << "Failed to queue supervision event"; ret = false; } return ret; } -std::unique_ptr ProcessStateNotifier::constructReceiver() +std::unique_ptr SupervisionControlNotifier::constructReceiver() { - return std::make_unique(ring_buffer_); + return std::make_unique(ring_buffer_); } } // namespace internal diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.hpp b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.hpp new file mode 100644 index 0000000000..c4d7d7cc03 --- /dev/null +++ b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.hpp @@ -0,0 +1,75 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#ifndef SUPERVISION_CONTROL_NOTIFIER_HPP_INCLUDED +#define SUPERVISION_CONTROL_NOTIFIER_HPP_INCLUDED + +#include "ipc_dropin/ringbuffer.hpp" +#include "score/mw/launch_manager/supervision_control_client/isupervision_control_notifier.hpp" + +namespace score +{ + +namespace lcm +{ + +namespace internal +{ + +/// @brief SupervisionControlNotifier implementation for forwarding supervision events to the alive monitor. +/// The Launch Manager creates an instance of this class to queue supervision events +/// (activation/deactivation) for the alive monitor to consume via the receiver. +class SupervisionControlNotifier final : public ISupervisionControlNotifier +{ + public: + /// @brief Constructor that creates the SupervisionControlNotifier. + SupervisionControlNotifier() noexcept; + + /// @brief Copy constructor is disabled. + SupervisionControlNotifier(const SupervisionControlNotifier&) noexcept = delete; + + /// @brief Move constructor is disabled. + SupervisionControlNotifier(SupervisionControlNotifier&&) noexcept = delete; + + /// @brief Copy-assign is disabled. + SupervisionControlNotifier& operator=(const SupervisionControlNotifier& other) = delete; + + /// @brief Move-assign is disabled. + SupervisionControlNotifier& operator=(SupervisionControlNotifier&& other) = delete; + + /// @brief Destructor. + ~SupervisionControlNotifier() noexcept; + + /// @brief Construct and return the receiver instance used to receive supervision events. + /// @return Supervision control receiver instance + std::unique_ptr constructReceiver() override; + + /// @brief Writes via IPC the latest supervision event, so that the alive monitor can be informed about it. + /// @param[in] f_event The SupervisionEvent to be queued + /// @returns True on success, false for failure + bool queueSupervisionEvent(const score::lcm::SupervisionEvent& f_event) noexcept override; + + private: + /// @brief Ring buffer through which supervision events are forwarded to the alive monitor + std::shared_ptr(score::lcm::BufferConstants::BUFFER_QUEUE_SIZE), + static_cast(score::lcm::BufferConstants::BUFFER_MAXPAYLOAD)>> + ring_buffer_{}; +}; + +} // namespace internal + +} // namespace lcm + +} // namespace score +#endif diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_event.hpp b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_event.hpp new file mode 100644 index 0000000000..2ef7f74213 --- /dev/null +++ b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_event.hpp @@ -0,0 +1,58 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#ifndef SUPERVISION_EVENT_HPP_INCLUDED +#define SUPERVISION_EVENT_HPP_INCLUDED + +#include "score/mw/launch_manager/common/identifier_hash.hpp" +#include +#include + +namespace score +{ + +namespace lcm +{ + +/// @brief Type of supervision event sent from the launch manager to the alive monitor. +enum class SupervisionEventType : std::uint8_t +{ + kActivation = 0, ///< Supervision should be activated (process reached running state). + kDeactivation = 1 ///< Supervision should be deactivated (process terminating or terminated). +}; + +// RULECHECKER_comment(1, 1, check_incomplete_data_member_construction, "This struct is POD, which doesn't have +// user-declared constructor. The rule doesn't apply.", false) +struct SupervisionEvent +{ + /// @brief Stores the Modelled Process ID as IdentifierHash. + score::lcm::IdentifierHash id; + + /// @brief The type of supervision event. + SupervisionEventType eventType; + + /// @brief Stores the timestamp based on the system clock when the event occurred. + timespec systemClockTimestamp; +}; + +enum class BufferConstants : size_t +{ + BUFFER_MAXPAYLOAD = sizeof(SupervisionEvent), ///< Ringbuffer max payload size + BUFFER_QUEUE_SIZE = 4096UL ///< Ringbuffer queue size +}; + +} // namespace lcm + +} // namespace score + +#endif // SUPERVISION_EVENT_HPP_INCLUDED From b6ca779d3e54813a2d885cfac8460769e54fdf9c Mon Sep 17 00:00:00 2001 From: William Roebuck <244554584+WilliamRoebuck@users.noreply.github.com> Date: Thu, 6 Aug 2026 13:40:25 +0100 Subject: [PATCH 02/13] Adapt to new code --- .../src/daemon/src/common/process_state.hpp | 12 ++--- score/launch_manager/src/daemon/src/main.cpp | 2 - .../src/process_group_manager/details/BUILD | 4 +- .../process_group_manager/details/graph.cpp | 11 +---- .../details/graph_UT.cpp | 9 +--- .../details/process_info_node.cpp | 24 +++++----- .../details/process_info_node.hpp | 11 +++-- .../details/process_info_node_UT.cpp | 5 ++- .../process_group_manager.hpp | 8 ---- .../src/supervision_control_client/BUILD | 25 +++++++++++ .../isupervision_control_notifier.hpp | 8 +--- .../isupervision_event_publisher.hpp | 45 +++++++++++++++++++ .../mock_supervision_event_publisher.hpp | 31 +++++++++++++ .../supervision_control_client_ut.cpp | 16 +++---- .../supervision_control_notifier.cpp | 10 +++++ .../supervision_control_notifier.hpp | 9 +++- 16 files changed, 157 insertions(+), 73 deletions(-) create mode 100644 score/launch_manager/src/daemon/src/supervision_control_client/isupervision_event_publisher.hpp create mode 100644 score/launch_manager/src/daemon/src/supervision_control_client/mock_supervision_event_publisher.hpp diff --git a/score/launch_manager/src/daemon/src/common/process_state.hpp b/score/launch_manager/src/daemon/src/common/process_state.hpp index 7c8e79cd49..95a622d7e6 100644 --- a/score/launch_manager/src/daemon/src/common/process_state.hpp +++ b/score/launch_manager/src/daemon/src/common/process_state.hpp @@ -16,10 +16,7 @@ #include -namespace score -{ - -namespace lcm +namespace score::lcm { /// @brief Represents the state of a modelled process. @@ -29,11 +26,10 @@ enum class ProcessState : std::uint8_t kStarting = 1, ///< process in starting state. kRunning = 2, ///< process in running state. kTerminating = 3, ///< process in terminating state. - kTerminated = 4 ///< process in terminated state. + kTerminated = 4, ///< process in terminated state. + kFailed = 5 ///< process failed to start. }; -} // namespace lcm - -} // namespace score +} // namespace score::lcm #endif // SCORE_LCM_PROCESS_STATE_HPP_INCLUDED diff --git a/score/launch_manager/src/daemon/src/main.cpp b/score/launch_manager/src/daemon/src/main.cpp index 56630f049f..791178e56b 100644 --- a/score/launch_manager/src/daemon/src/main.cpp +++ b/score/launch_manager/src/daemon/src/main.cpp @@ -157,8 +157,6 @@ int main(int argc, const char* argv[]) } LM_LOG_DEBUG() << "Launch Manager Started !!!!"; std::shared_ptr recoveryClient{std::make_shared()}; - std::unique_ptr watchdog{ - std::make_unique()}; auto supervision_control_notifier = std::make_unique(); std::unique_ptr healthMonitor{ std::make_unique( diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/BUILD b/score/launch_manager/src/daemon/src/process_group_manager/details/BUILD index 2d34d3375b..65bfaf79c2 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/BUILD +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/BUILD @@ -150,7 +150,7 @@ cc_library( "//score/launch_manager/src/daemon/src/osal:ipc_comms", "//score/launch_manager/src/daemon/src/osal:semaphore", "//score/launch_manager/src/daemon/src/process_group_manager:iprocess", - "//score/launch_manager/src/daemon/src/supervision_control_client", + "//score/launch_manager/src/daemon/src/supervision_control_client:isupervision_event_publisher", "@score_baselibs//score/language/futurecpp", ], ) @@ -162,6 +162,7 @@ cc_test( ":process_info_node", ":safe_process_map", "//score/launch_manager/src/daemon/src/process_group_manager:mock_iprocess", + "//score/launch_manager/src/daemon/src/supervision_control_client:mock_supervision_event_publisher", "@googletest//:gtest_main", ], ) @@ -209,6 +210,7 @@ cc_test( ":graph", "//score/launch_manager/src/daemon/src/configuration:configuration_adapter", "//score/launch_manager/src/daemon/src/process_group_manager:mock_iprocess", + "//score/launch_manager/src/daemon/src/supervision_control_client:mock_supervision_event_publisher", "@googletest//:gtest_main", ], ) diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp index bdd3322063..071a6e4526 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp @@ -99,15 +99,6 @@ void Graph::createProcessInfoNodes(uint32_t num_processes) ? ProcessInfoNode::ReadyCondition::kTerminated : ProcessInfoNode::ReadyCondition::kRunning; - auto report_state_lambda = [this](IdentifierHash id, ProcessState state, timespec timestamp) { - score::lcm::PosixProcess process_info; - process_info.id = id; - process_info.processStateId = state; - process_info.processGroupStateId = getProcessGroupState(); - process_info.systemClockTimestamp = timestamp; - return supervision_control_notifier_->queuePosixProcess(process_info); - }; - const auto* config = configuration_->getOsProcessConfiguration(getProcessGroupName(), process_id).value_or(nullptr); if (!config) @@ -121,7 +112,7 @@ void Graph::createProcessInfoNodes(uint32_t num_processes) config, process_id, ready_condition, - report_state_lambda, + supervision_control_notifier_, process_interface_, process_map_); static_cast(index); diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp index 720980ead7..38a6850efc 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp @@ -17,6 +17,8 @@ #include "score/mw/launch_manager/configuration/configuration_adapter.hpp" #include "score/mw/launch_manager/process_group_manager/details/graph.hpp" #include "score/mw/launch_manager/process_group_manager/mock_iprocess.hpp" +#include "score/mw/launch_manager/process_group_manager/process_group_manager.hpp" +#include "score/mw/launch_manager/supervision_control_client/mock_supervision_event_publisher.hpp" namespace score::lcm::internal { @@ -32,13 +34,6 @@ class MockProcessMap : public SafeProcessMapInserter MOCK_METHOD(SafeProcessMapReturnType, insertIfNotTerminated, (osal::ProcessID key, IComponent* object), (override)); }; -class MockProcessStateNotifier : public ISupervisionControlNotifier -{ - public: - MOCK_METHOD(std::unique_ptr, constructReceiver, (), (override)); - MOCK_METHOD(bool, queueSupervisionEvent, (const score::lcm::SupervisionEvent& f_event), (override, noexcept)); -}; - class MockTransitionResultPublisher : public ITransitionResultPublisher { public: diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp index b06046bc2a..d66de96c65 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp @@ -31,7 +31,7 @@ ProcessInfoNode::ProcessInfoNode( const OsProcess* config, uint32_t index, ReadyCondition ready_condition, - ReportStateFn report_function, + ISupervisionEventPublisher* state_publisher, osal::IProcess* process_interface, std::shared_ptr process_map) : terminator_(), @@ -42,7 +42,7 @@ ProcessInfoNode::ProcessInfoNode( process_state_(score::lcm::ProcessState::kIdle), ready_condition_(ready_condition), config_(config), - report_state_(std::move(report_function)), + state_publisher_(state_publisher), process_interface_(process_interface), process_map_(std::move(process_map)) { @@ -116,24 +116,22 @@ bool ProcessInfoNode::setState(score::lcm::ProcessState new_state) score::lcm::ProcessState::kIdle != new_state) { // for a reporting process, report a process state change to PHM - std::optional eventType; + timespec timestamp{}; + static_cast(clock_gettime(CLOCK_MONOTONIC, ×tamp)); + + // Note that we ignore the return value. + // An error would indicate that PHM is not reading values fast enough from the shared memory; the buffer + // over-run should be visible at the PHM side and handled there. If PHM is not responding do we need to handle + // this? If PHM terminates state manager will be informed in any case. if (new_state == score::lcm::ProcessState::kRunning) { - eventType = score::lcm::SupervisionEventType::kActivation; + state_publisher_->reportActivation(config_->process_id_, timestamp); } else if ( new_state == score::lcm::ProcessState::kTerminating || new_state == score::lcm::ProcessState::kTerminated) { - eventType = score::lcm::SupervisionEventType::kDeactivation; + state_publisher_->reportDeactivation(config_->process_id_, timestamp); } - - timespec timestamp{}; - static_cast(clock_gettime(CLOCK_MONOTONIC, ×tamp)); - // Note that we ignore the return value. - // An error would indicate that PHM is not reading values fast enough from the shared memory; the buffer - // over-run should be visible at the PHM side and handled there. If PHM is not responding do we need to handle - // this? If PHM terminates state manager will be informed in any case. - static_cast(report_state_(config_->process_id_, eventType, timestamp)); } return success; diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp index 42cb80cad5..2b2c059dc9 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp @@ -18,6 +18,7 @@ #include "score/mw/launch_manager/control/control_client_channel.hpp" #include "score/mw/launch_manager/process_group_manager/details/icomponent.hpp" #include "score/mw/launch_manager/process_group_manager/details/safe_process_map.hpp" +#include "score/mw/launch_manager/supervision_control_client/isupervision_event_publisher.hpp" #include #include @@ -32,8 +33,6 @@ namespace internal using namespace score::mw::lifecycle::internal; -using ReportStateFn = std::function; - /// @brief Represents both a process and a component in the graph. /// @details A ProcessInfoNode is a node in the dependency graph that represents an OS process and its associated /// component. It manages the lifecycle of the process, including activation, deactivation, and state reporting. The @@ -57,14 +56,14 @@ class ProcessInfoNode final : public IComponent /// @param config Configuration for the OS process. /// @param index The process index within its process group. /// @param ready_condition Whether this process is considered ready when running or when terminated. - /// @param report_function Callback used to report state changes to the platform health manager. + /// @param state_publisher Interface used to report state changes to the platform health manager. /// @param process_interface The OS process interface used to start and stop the process. /// @param process_map The shared process map used to track process pids. ProcessInfoNode( const OsProcess* config, uint32_t index, ReadyCondition ready_condition, - ReportStateFn report_function, + ISupervisionEventPublisher* state_publisher, osal::IProcess* process_interface, std::shared_ptr process_map); @@ -203,8 +202,8 @@ class ProcessInfoNode final : public IComponent /// @brief Pointer to the comms for this process osal::IpcCommsP sync_{nullptr}; - /// @brief Callback for reporting process state to health monitor - ReportStateFn report_state_; + /// @brief Interface for reporting component state to health monitor + ISupervisionEventPublisher* state_publisher_; /// @brief True if we have returned a success or failure for the current activation/deactivation std::atomic_flag success_returned_{false}; diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node_UT.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node_UT.cpp index b2246439e1..2b3279c733 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node_UT.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node_UT.cpp @@ -14,6 +14,7 @@ #include "score/mw/launch_manager/process_group_manager/details/process_info_node.hpp" #include "score/mw/launch_manager/process_group_manager/details/safe_process_map.hpp" #include "score/mw/launch_manager/process_group_manager/mock_iprocess.hpp" +#include "score/mw/launch_manager/supervision_control_client/mock_supervision_event_publisher.hpp" #include #include #include @@ -56,7 +57,7 @@ class ProcessInfoNodeFixture : public ::testing::Test config_.pgm_config_ = pgm_config; return std::make_unique( - &config_, kProcessIndex, ready_condition, report_fn_, &mock_processIf_, process_map_); + &config_, kProcessIndex, ready_condition, &mock_publisher_, &mock_processIf_, process_map_); } /// @brief Helper method to create a ProcessInfoNode that is self-terminating. @@ -122,7 +123,7 @@ class ProcessInfoNodeFixture : public ::testing::Test std::shared_ptr process_map_{std::make_shared()}; StrictMock mock_processIf_{}; MockFunction mock_report_fn_{}; - ReportStateFn report_fn_{mock_report_fn_.AsStdFunction()}; + MockSupervisionEventPublisher mock_publisher_{}; }; // Bundles different cases for activate() that occur during startup, before the ready condition is reached. diff --git a/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.hpp b/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.hpp index 74aa4ed1a8..765ffc511f 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.hpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.hpp @@ -146,14 +146,6 @@ class ProcessGroupManager final : public ITransitionResultPublisher /// @return Shared pointer to the MpmcQueue object for ProcessInfoNode jobs. std::shared_ptr getWorkerJobs(); - /// @brief Control Activation / Deactivation of alive supervisions - /// @param[in] f_event The SupervisionEvent to be queued - /// @returns True on success, false for failure - bool queueSupervisionEvent(const score::lcm::SupervisionEvent& f_event) - { - return supervision_control_notifier_->queueSupervisionEvent(f_event); - } - /// @brief Cancels processGroupManager main routine as though SIGTERM had been sent void cancel(); diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/BUILD b/score/launch_manager/src/daemon/src/supervision_control_client/BUILD index 9bdaf78ca4..8f3ec34f1e 100644 --- a/score/launch_manager/src/daemon/src/supervision_control_client/BUILD +++ b/score/launch_manager/src/daemon/src/supervision_control_client/BUILD @@ -45,6 +45,31 @@ cc_library( deps = [ ":isupervision_control_receiver", ":supervision_event", + ":isupervision_event_publisher" + ], +) + +cc_library( + name = "isupervision_event_publisher", + hdrs = ["isupervision_event_publisher.hpp"], + include_prefix = "score/mw/launch_manager/supervision_control_client", + strip_include_prefix = "/score/launch_manager/src/daemon/src/supervision_control_client", + visibility = ["//score:__subpackages__"], + deps = [ + "//score/launch_manager/src/daemon/src/common:identifier_hash", + ], +) + +cc_library( + name = "mock_supervision_event_publisher", + hdrs = ["mock_supervision_event_publisher.hpp"], + testonly = True, + include_prefix = "score/mw/launch_manager/supervision_control_client", + strip_include_prefix = "/score/launch_manager/src/daemon/src/supervision_control_client", + visibility = ["//score:__subpackages__"], + deps = [ + ":isupervision_event_publisher", + "@googletest//:gtest_main", ], ) diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/isupervision_control_notifier.hpp b/score/launch_manager/src/daemon/src/supervision_control_client/isupervision_control_notifier.hpp index 5391e65fbf..22a5adad2d 100644 --- a/score/launch_manager/src/daemon/src/supervision_control_client/isupervision_control_notifier.hpp +++ b/score/launch_manager/src/daemon/src/supervision_control_client/isupervision_control_notifier.hpp @@ -14,6 +14,7 @@ #define ISUPERVISION_CONTROL_NOTIFIER_HPP_INCLUDED #include "score/mw/launch_manager/supervision_control_client/isupervision_control_receiver.hpp" +#include "score/mw/launch_manager/supervision_control_client/isupervision_event_publisher.hpp" #include "score/mw/launch_manager/supervision_control_client/supervision_event.hpp" namespace score @@ -25,7 +26,7 @@ namespace lcm /// @brief ISupervisionControlNotifier interface for forwarding supervision events to the alive monitor. /// The Launch Manager uses this interface to notify the alive monitor whenever a supervised /// process reaches running state (activation) or starts terminating (deactivation). -class ISupervisionControlNotifier +class ISupervisionControlNotifier : public ISupervisionEventPublisher { public: /// @brief Destructor. @@ -34,11 +35,6 @@ class ISupervisionControlNotifier /// @brief Construct and return the receiver instance used to receive supervision events. /// @return Supervision control receiver instance virtual std::unique_ptr constructReceiver() = 0; - - /// @brief Writes via IPC the latest supervision event, so that the alive monitor can be informed about it. - /// @param[in] f_event The SupervisionEvent to be queued - /// @returns True on success, false for failure - virtual bool queueSupervisionEvent(const score::lcm::SupervisionEvent& f_event) noexcept = 0; }; } // namespace lcm diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/isupervision_event_publisher.hpp b/score/launch_manager/src/daemon/src/supervision_control_client/isupervision_event_publisher.hpp new file mode 100644 index 0000000000..cb25e3e14f --- /dev/null +++ b/score/launch_manager/src/daemon/src/supervision_control_client/isupervision_event_publisher.hpp @@ -0,0 +1,45 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef ISUPERVISION_EVENT_PUBLISHER_HPP_INCLUDED +#define ISUPERVISION_EVENT_PUBLISHER_HPP_INCLUDED + +#include "score/mw/launch_manager/common/identifier_hash.hpp" +#include + +namespace score +{ + +namespace lcm +{ + +/// @brief ISupervisionEventPublisher interface for forwarding supervision events to the alive monitor. +/// The Launch Manager uses this interface to notify the alive monitor whenever a supervised +/// process reaches the active state or inactive state +class ISupervisionEventPublisher +{ + public: + /// @brief Destructor. + virtual ~ISupervisionEventPublisher() noexcept = default; + + /// @brief Report that process with @param id has reached the active state at @param time + virtual bool reportActivation(IdentifierHash id, timespec time) noexcept = 0; + + /// @brief Report that process with @param id has changed from the active state at @param time + virtual bool reportDeactivation(IdentifierHash id, timespec time) noexcept = 0; +}; + +} // namespace lcm + +} // namespace score + +#endif diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/mock_supervision_event_publisher.hpp b/score/launch_manager/src/daemon/src/supervision_control_client/mock_supervision_event_publisher.hpp new file mode 100644 index 0000000000..31691fc446 --- /dev/null +++ b/score/launch_manager/src/daemon/src/supervision_control_client/mock_supervision_event_publisher.hpp @@ -0,0 +1,31 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef MOCK_SUPERVISION_EVENT_PUBLISHER_HPP_INCLUDED +#define MOCK_SUPERVISION_EVENT_PUBLISHER_HPP_INCLUDED + +#include "score/mw/launch_manager/supervision_control_client/isupervision_event_publisher.hpp" +#include + +namespace score::lcm +{ + +class MockSupervisionEventPublisher : public ISupervisionEventPublisher +{ + public: + MOCK_METHOD(bool, reportActivation, (IdentifierHash id, timespec time), (override, noexcept)); + MOCK_METHOD(bool, reportDeactivation, (IdentifierHash id, timespec time), (override, noexcept)); +}; + +} // namespace score::lcm + +#endif // MOCK_SUPERVISION_EVENT_PUBLISHER_HPP_INCLUDED diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp index 4cdb56006b..d1e6a1bd8f 100644 --- a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp +++ b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp @@ -59,9 +59,9 @@ TEST_F(SupervisionControlClient_UT, SupervisionControlClient_QueueOneEvent_Succe SupervisionEvent event1{ .id = score::lcm::IdentifierHash("Process1"), .eventType = score::lcm::SupervisionEventType::kActivation, - }; + .systemClockTimestamp = {}}; - bool queued = notifier_->queueSupervisionEvent(event1); + bool queued = notifier_->reportActivation(event1.id, event1.systemClockTimestamp); ASSERT_TRUE(queued); auto result = receiver_->getNextSupervisionEvent(); @@ -87,8 +87,8 @@ TEST_F(SupervisionControlClient_UT, SupervisionControlClient_QueueMaxNumberOfEve SupervisionEvent event{ .id = score::lcm::IdentifierHash("Process" + std::to_string(i)), .eventType = score::lcm::SupervisionEventType::kActivation, - }; - bool queued = notifier_->queueSupervisionEvent(event); + .systemClockTimestamp = {}}; + bool queued = notifier_->reportActivation(event.id, event.systemClockTimestamp); ASSERT_TRUE(queued) << "Failed to queue event at index " << i; } @@ -114,19 +114,19 @@ TEST_F(SupervisionControlClient_UT, SupervisionControlClient_QueueOneEventTooMan SupervisionEvent event1{ .id = score::lcm::IdentifierHash("Process1"), .eventType = score::lcm::SupervisionEventType::kActivation, - }; + .systemClockTimestamp = {}}; for (size_t i = 0; i < static_cast(BufferConstants::BUFFER_QUEUE_SIZE); ++i) { SupervisionEvent event{ .id = score::lcm::IdentifierHash("Process" + std::to_string(i)), .eventType = score::lcm::SupervisionEventType::kActivation, - }; - bool queued = notifier_->queueSupervisionEvent(event); + .systemClockTimestamp = {}}; + bool queued = notifier_->reportActivation(event.id, event.systemClockTimestamp); ASSERT_TRUE(queued) << "Failed to queue event at index " << i; } - bool queued = notifier_->queueSupervisionEvent(event1); + bool queued = notifier_->reportActivation(event1.id, event1.systemClockTimestamp); ASSERT_FALSE(queued) << "Expected queuing to fail due to full buffer"; auto result = receiver_->getNextSupervisionEvent(); diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.cpp b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.cpp index 6b432cb6b9..361a6b4c9f 100644 --- a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.cpp +++ b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.cpp @@ -35,6 +35,16 @@ SupervisionControlNotifier::~SupervisionControlNotifier() noexcept { } +bool SupervisionControlNotifier::reportActivation(IdentifierHash id, timespec time) noexcept +{ + return queueSupervisionEvent({id, SupervisionEventType::kActivation, time}); +} + +bool SupervisionControlNotifier::reportDeactivation(IdentifierHash id, timespec time) noexcept +{ + return queueSupervisionEvent({id, SupervisionEventType::kDeactivation, time}); +} + bool SupervisionControlNotifier::queueSupervisionEvent(const score::lcm::SupervisionEvent& f_event) noexcept { bool ret = true; diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.hpp b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.hpp index c4d7d7cc03..39c6d739bc 100644 --- a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.hpp +++ b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.hpp @@ -16,6 +16,7 @@ #include "ipc_dropin/ringbuffer.hpp" #include "score/mw/launch_manager/supervision_control_client/isupervision_control_notifier.hpp" +#include "score/mw/launch_manager/supervision_control_client/supervision_event.hpp" namespace score { @@ -54,12 +55,16 @@ class SupervisionControlNotifier final : public ISupervisionControlNotifier /// @return Supervision control receiver instance std::unique_ptr constructReceiver() override; + bool reportActivation(IdentifierHash id, timespec time) noexcept override; + + bool reportDeactivation(IdentifierHash id, timespec time) noexcept override; + + private: /// @brief Writes via IPC the latest supervision event, so that the alive monitor can be informed about it. /// @param[in] f_event The SupervisionEvent to be queued /// @returns True on success, false for failure - bool queueSupervisionEvent(const score::lcm::SupervisionEvent& f_event) noexcept override; + bool queueSupervisionEvent(const score::lcm::SupervisionEvent& f_event) noexcept; - private: /// @brief Ring buffer through which supervision events are forwarded to the alive monitor std::shared_ptr(score::lcm::BufferConstants::BUFFER_QUEUE_SIZE), From 9085aa34dbe9d16c1cac326508dc3e8ce5606ea3 Mon Sep 17 00:00:00 2001 From: William Roebuck <244554584+WilliamRoebuck@users.noreply.github.com> Date: Thu, 6 Aug 2026 15:33:54 +0100 Subject: [PATCH 03/13] Fixes after rebase --- BUILD | 2 +- .../details/daemon/AliveMonitorImpl.cpp | 4 -- .../process_group_manager/details/graph.cpp | 8 +-- .../process_group_manager/details/graph.hpp | 11 ++-- .../details/graph_UT.cpp | 7 +-- .../details/process_info_node.cpp | 42 +++++++-------- .../details/process_info_node.hpp | 3 ++ .../details/process_info_node_UT.cpp | 54 ++++--------------- 8 files changed, 48 insertions(+), 83 deletions(-) diff --git a/BUILD b/BUILD index 6927fdf895..9040902cb7 100644 --- a/BUILD +++ b/BUILD @@ -24,7 +24,7 @@ refresh_compile_commands( exclude_external_sources = True, target_compatible_with = ["@platforms//os:linux"], targets = { - "//...": "", + "//score/...": "", }, ) diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp index 819b01035c..14d2ea754f 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp @@ -45,11 +45,7 @@ EInitCode AliveMonitorImpl::init() noexcept m_osClock.startMeasurement(); m_daemon = std::make_unique(m_osClock, std::move(m_process_state_receiver)); -#ifdef USE_NEW_CONFIGURATION initResult = m_daemon->init(m_recovery_client, m_config); -#else - initResult = m_daemon->init(m_recovery_client); -#endif if (initResult == EInitCode::kNoError) { diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp index 071a6e4526..7090cc46f2 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp @@ -35,11 +35,11 @@ namespace internal Graph::Graph( uint32_t max_num_nodes, - ConfigurationInterface* configuration, + ConfigurationAdapter* configuration, std::shared_ptr job_queue, osal::IProcess* process_interface, std::shared_ptr process_map, - ISupervisionControlNotifier* supervision_control_notifier, + ISupervisionEventPublisher* supervision_event_publisher, ITransitionResultPublisher* transition_result_receiver) : pg_index_(0U), nodes_(max_num_nodes), @@ -50,7 +50,7 @@ Graph::Graph( job_queue_(job_queue), process_interface_(process_interface), process_map_(process_map), - supervision_control_notifier_(supervision_control_notifier), + supervision_event_publisher_(supervision_event_publisher), transition_result_receiver_(transition_result_receiver), last_state_manager_(), last_execution_error_(0U), @@ -112,7 +112,7 @@ void Graph::createProcessInfoNodes(uint32_t num_processes) config, process_id, ready_condition, - supervision_control_notifier_, + supervision_event_publisher_, process_interface_, process_map_); static_cast(index); diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.hpp b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.hpp index 15ba92b5a0..382c0eae5b 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.hpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.hpp @@ -36,7 +36,7 @@ #include "score/mw/launch_manager/process_group_manager/details/run_target.hpp" #include "score/mw/launch_manager/process_group_manager/details/transition.hpp" #include "score/mw/launch_manager/process_group_manager/iprocess.hpp" -#include "score/mw/launch_manager/supervision_control_client/isupervision_control_notifier.hpp" +#include "score/mw/launch_manager/supervision_control_client/isupervision_event_publisher.hpp" #include namespace score @@ -50,7 +50,6 @@ namespace internal using namespace score::mw::lifecycle; -using ConfigurationInterface = ConfigurationAdapter; using Config = score::mw::launch_manager::configuration::Config; using WorkerQueue = @@ -153,11 +152,11 @@ class Graph final /// @param max_num_nodes Maximum number of nodes this graph can hold. Graph( uint32_t max_num_nodes, - ConfigurationInterface* configuration, + ConfigurationAdapter* configuration, std::shared_ptr job_queue, osal::IProcess* process_interface, std::shared_ptr process_map, - ISupervisionControlNotifier* supervision_control_notifier, + ISupervisionEventPublisher* supervision_event_publisher, ITransitionResultPublisher* transition_result_receiver); /// @brief Destructor to clean up resources used by the Graph object. @@ -379,7 +378,7 @@ class Graph final mutable std::mutex requested_state_mutex_{}; /// @brief Config pointer to set up graph nodes - ConfigurationInterface* configuration_; + ConfigurationAdapter* configuration_; /// @brief Queue to push component tasks to std::shared_ptr job_queue_; @@ -391,7 +390,7 @@ class Graph final std::shared_ptr process_map_; /// @brief Interface to pass process nodes for alive monitor notifications - ISupervisionControlNotifier* supervision_control_notifier_; + ISupervisionEventPublisher* supervision_event_publisher_; /// @brief Class to receive information about the initial state transition result ITransitionResultPublisher* transition_result_receiver_; diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp index 38a6850efc..8f9fd80394 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp @@ -48,7 +48,8 @@ class GraphTest : public ::testing::Test RecordProperty("TestType", "interface-test"); RecordProperty("DerivationTechnique", "equivalence-classes"); - ON_CALL(mock_supervision_control_notifier_, queuePosixProcess).WillByDefault(Return(true)); + ON_CALL(mock_supervision_event_publisher_, reportActivation).WillByDefault(Return(true)); + ON_CALL(mock_supervision_event_publisher_, reportDeactivation).WillByDefault(Return(true)); auto procs = SetConfig(); @@ -180,7 +181,7 @@ class GraphTest : public ::testing::Test std::shared_ptr job_queue_ = std::make_shared(); StrictMock process_interface_{}; std::shared_ptr mock_process_map = std::make_shared(); - NiceMock mock_supervision_control_notifier_{}; + NiceMock mock_supervision_event_publisher_{}; MockTransitionResultPublisher mock_transition_result_publisher_{}; Graph graph_{ 10U, @@ -188,7 +189,7 @@ class GraphTest : public ::testing::Test job_queue_, &process_interface_, mock_process_map, - &mock_supervision_control_notifier_, + &mock_supervision_event_publisher_, &mock_transition_result_publisher_}; static constexpr std::string_view pg_string{"MainPG"}; diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp index d66de96c65..5fcbf7f0e3 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp @@ -77,11 +77,27 @@ IComponent::RequestResult ProcessInfoNode::tryReportSuccess() if (!success_returned_.test_and_set()) { reached_ready_.store(true); + + if (auto time = getTimeForReport()) + { + state_publisher_->reportActivation(config_->process_id_, time.value()); + } + return {RequestState::kSuccess}; } return {IComponent::RequestState::kWaiting}; } +std::optional ProcessInfoNode::getTimeForReport() const { + if (config_->startup_config_.comms_type_ == osal::CommsType::kNoComms) { + return std::nullopt; + } + + timespec timestamp{}; + static_cast(clock_gettime(CLOCK_MONOTONIC, ×tamp)); + return timestamp; +} + IComponent::RequestResult ProcessInfoNode::tryReportError(ComponentError error) { if (!success_returned_.test_and_set()) @@ -112,28 +128,6 @@ bool ProcessInfoNode::setState(score::lcm::ProcessState new_state) success = false; } - if (success && config_->startup_config_.comms_type_ != osal::CommsType::kNoComms && - score::lcm::ProcessState::kIdle != new_state) - { - // for a reporting process, report a process state change to PHM - timespec timestamp{}; - static_cast(clock_gettime(CLOCK_MONOTONIC, ×tamp)); - - // Note that we ignore the return value. - // An error would indicate that PHM is not reading values fast enough from the shared memory; the buffer - // over-run should be visible at the PHM side and handled there. If PHM is not responding do we need to handle - // this? If PHM terminates state manager will be informed in any case. - if (new_state == score::lcm::ProcessState::kRunning) - { - state_publisher_->reportActivation(config_->process_id_, timestamp); - } - else if ( - new_state == score::lcm::ProcessState::kTerminating || new_state == score::lcm::ProcessState::kTerminated) - { - state_publisher_->reportDeactivation(config_->process_id_, timestamp); - } - } - return success; } @@ -418,6 +412,10 @@ IComponent::RequestResult ProcessInfoNode::deactivate(score::cpp::stop_token sto { success_returned_.clear(); reached_ready_.store(false); + if (auto time = getTimeForReport()) + { + state_publisher_->reportDeactivation(config_->process_id_, time.value()); + } terminateProcess(stop_token); setState(ProcessState::kIdle); return IComponent::RequestState::kSuccess; diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp index 2b2c059dc9..26b490dfe1 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp @@ -119,6 +119,9 @@ class ProcessInfoNode final : public IComponent /// @brief Helper method to post on the semaphore waiting for kRunning if it exists void unblockSync(); + /// @brief If this process is configured to report to alive monitor, return the current time + [[nodiscard]] std::optional getTimeForReport() const; + /// @brief Get the request result corresponding to the new state reached. For example, if the ready state is /// terminated, the function will only return kSuccess if the new state is kTerminated. /// @return Success if the ready condition is satisfied and completion is not already reported, an error if the diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node_UT.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node_UT.cpp index 2b3279c733..414fdcb2b4 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node_UT.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node_UT.cpp @@ -40,6 +40,9 @@ class ProcessInfoNodeFixture : public ::testing::Test { RecordProperty("TestType", "interface-test"); RecordProperty("DerivationTechnique", "equivalence-classes"); + + ON_CALL(mock_publisher_, reportActivation).WillByDefault(Return(true)); + ON_CALL(mock_publisher_, reportDeactivation).WillByDefault(Return(true)); } /// @brief Helper method to create a ProcessInfoNode with the given parameters. @@ -89,16 +92,6 @@ class ProcessInfoNodeFixture : public ::testing::Test return createRunningProcessInfoNode(osal::CommsType::kReporting, termination_timeout); } - /// @brief Asserts that mock_report_fn_ is called with each of the given states, in the given order. - void expectStateTransitions(const std::vector& states) - { - Sequence seq; - for (const auto state : states) - { - EXPECT_CALL(mock_report_fn_, Call(_, state, _)).InSequence(seq).WillOnce(Return(true)); - } - } - /// @brief Sets up expectations for the OS process being launched and successfully added to the process map. void expectSuccessfulProcessLaunch() { @@ -122,8 +115,7 @@ class ProcessInfoNodeFixture : public ::testing::Test score::cpp::stop_source stop_source_{}; std::shared_ptr process_map_{std::make_shared()}; StrictMock mock_processIf_{}; - MockFunction mock_report_fn_{}; - MockSupervisionEventPublisher mock_publisher_{}; + NiceMock mock_publisher_{}; }; // Bundles different cases for activate() that occur during startup, before the ready condition is reached. @@ -170,7 +162,7 @@ TEST_F(ProcessInfoNodeStartupTest, CanStartReportingProcess_ReportsRunningInTime auto node = createProcessInfoNode(osal::CommsType::kReporting); expectSuccessfulProcessLaunch(); EXPECT_CALL(mock_processIf_, waitForkRunning(_, _)).WillOnce(Return(osal::OsalReturnType::kSuccess)); - expectStateTransitions({score::lcm::ProcessState::kStarting, score::lcm::ProcessState::kRunning}); + EXPECT_CALL(mock_publisher_, reportActivation); auto result = node->activate(score::cpp::stop_token{}); @@ -274,10 +266,7 @@ TEST_F(ProcessInfoNodeStartupCrashTest, ProcesssTerminated_OnWaitForkRunningTime EXPECT_CALL(mock_processIf_, waitForkRunning(_, _)).WillOnce(Return(osal::OsalReturnType::kFail)); // Simulate the OS handler reporting the killed process's exit once termination is requested. expectOsAcknowledgesTermination(node.get()); - expectStateTransitions( - {score::lcm::ProcessState::kStarting, - score::lcm::ProcessState::kTerminating, - score::lcm::ProcessState::kTerminated}); + EXPECT_CALL(mock_publisher_, reportActivation).Times(0); auto result = node->activate(score::cpp::stop_token{}); @@ -302,7 +291,7 @@ TEST_F(ProcessInfoNodeStartupCrashTest, ReportingProcess_CrashesBeforeReady_NoRe node->tryHandleTermination(-1); }), Return(osal::OsalReturnType::kFail))); - expectStateTransitions({score::lcm::ProcessState::kStarting, score::lcm::ProcessState::kTerminated}); + EXPECT_CALL(mock_publisher_, reportActivation).Times(0); auto result = node->activate(score::cpp::stop_token{}); @@ -337,15 +326,7 @@ TEST_F(ProcessInfoNodeStartupCrashTest, ReportingProcess_CrashesBeforeReady_With node->tryHandleTermination(-1); }), Return(osal::OsalReturnType::kFail))); - expectStateTransitions( - {score::lcm::ProcessState::kStarting, - score::lcm::ProcessState::kTerminated, - score::lcm::ProcessState::kStarting, - score::lcm::ProcessState::kTerminated, - score::lcm::ProcessState::kStarting, - score::lcm::ProcessState::kTerminated, - score::lcm::ProcessState::kStarting, - score::lcm::ProcessState::kTerminated}); + EXPECT_CALL(mock_publisher_, reportActivation).Times(0); auto result = node->activate(score::cpp::stop_token{}); @@ -425,12 +406,7 @@ TEST_F(ProcessInfoNodeStartupCrashTest, TimeoutThenSuccess_WithRestarts) .WillOnce(Return(osal::OsalReturnType::kSuccess)); // Simulate the OS handler reporting the killed process's exit on the first (timed-out) attempt. expectOsAcknowledgesTermination(node.get()); - expectStateTransitions( - {score::lcm::ProcessState::kStarting, - score::lcm::ProcessState::kTerminating, - score::lcm::ProcessState::kTerminated, - score::lcm::ProcessState::kStarting, - score::lcm::ProcessState::kRunning}); + EXPECT_CALL(mock_publisher_, reportActivation); auto result = node->activate(score::cpp::stop_token{}); @@ -530,11 +506,7 @@ TEST_F(ProcessInfoNodeDeactivationTest, CanTerminateNonSelfTerminatingProcess) "to kTerminated."); EXPECT_CALL(mock_processIf_, waitForkRunning(_, _)).WillOnce(Return(osal::OsalReturnType::kSuccess)); - expectStateTransitions( - {score::lcm::ProcessState::kStarting, - score::lcm::ProcessState::kRunning, - score::lcm::ProcessState::kTerminating, - score::lcm::ProcessState::kTerminated}); + EXPECT_CALL(mock_publisher_, reportDeactivation); auto node = createRunningProcessInfoNode(osal::CommsType::kReporting); // Simulate the OS handler reporting the process's exit once termination is requested. @@ -597,11 +569,7 @@ TEST_F(ProcessInfoNodeDeactivationTest, ProcessIgnoresSigterm_ForcedWithSigkill) "SIGKILL."); EXPECT_CALL(mock_processIf_, waitForkRunning(_, _)).WillOnce(Return(osal::OsalReturnType::kSuccess)); - expectStateTransitions( - {score::lcm::ProcessState::kStarting, - score::lcm::ProcessState::kRunning, - score::lcm::ProcessState::kTerminating, - score::lcm::ProcessState::kTerminated}); + EXPECT_CALL(mock_publisher_, reportDeactivation); auto node = createRunningProcessInfoNode_TermTimeout(std::chrono::milliseconds{0}); EXPECT_CALL(mock_processIf_, requestTermination(_)).WillOnce(Return(osal::OsalReturnType::kSuccess)); From 56dcee261dabb7f9d4e79ff9cbb6c1204ad8709c Mon Sep 17 00:00:00 2001 From: William Roebuck <244554584+WilliamRoebuck@users.noreply.github.com> Date: Fri, 7 Aug 2026 08:41:25 +0100 Subject: [PATCH 04/13] Cleanup --- BUILD | 2 +- score/launch_manager/src/daemon/BUILD | 2 +- .../details/ifappl/MonitorIfDaemon.cpp | 29 ++++++++----------- .../src/daemon/src/configuration/BUILD | 4 +-- .../daemon/src/process_group_manager/BUILD | 2 +- .../details/process_info_node.cpp | 6 ++-- .../src/supervision_control_client/BUILD | 4 +-- 7 files changed, 23 insertions(+), 26 deletions(-) diff --git a/BUILD b/BUILD index 9040902cb7..6927fdf895 100644 --- a/BUILD +++ b/BUILD @@ -24,7 +24,7 @@ refresh_compile_commands( exclude_external_sources = True, target_compatible_with = ["@platforms//os:linux"], targets = { - "//score/...": "", + "//...": "", }, ) diff --git a/score/launch_manager/src/daemon/BUILD b/score/launch_manager/src/daemon/BUILD index 47903a6e3c..34705a5949 100644 --- a/score/launch_manager/src/daemon/BUILD +++ b/score/launch_manager/src/daemon/BUILD @@ -28,8 +28,8 @@ cc_binary( "//score/launch_manager/src/daemon/src/osal:ipc_comms", "//score/launch_manager/src/daemon/src/process_group_manager", "//score/launch_manager/src/daemon/src/process_group_manager:alive_monitor_thread", - "//score/launch_manager/src/daemon/src/supervision_control_client:supervision_control_notifier", "//score/launch_manager/src/daemon/src/recovery_client", + "//score/launch_manager/src/daemon/src/supervision_control_client:supervision_control_notifier", "//score/launch_manager/src/daemon/src/watchdog:watchdog_factory", "@score_baselibs//score/language/futurecpp", ], diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.cpp index 6cbd78ff46..714f996f0a 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/MonitorIfDaemon.cpp @@ -44,24 +44,19 @@ void MonitorIfDaemon::attachCheckpoint(Checkpoint& f_checkpoint_r) noexcept(fals void MonitorIfDaemon::updateData(const ifexm::ProcessState& f_observable_r) noexcept(true) { - const score::lcm::SupervisionEventType eventType{f_observable_r.getEventType()}; - - if (eventType == score::lcm::SupervisionEventType::kActivation) - { - if (isDeactivateRequest) - { - isProcessRestarted = true; - } - isActivateRequest = true; - isDeactivateRequest = false; - } - else if (eventType == score::lcm::SupervisionEventType::kDeactivation) - { - isDeactivateRequest = true; - } - else + switch (f_observable_r.getEventType()) { - // do nothing + case score::lcm::SupervisionEventType::kActivation: + if (isDeactivateRequest) + { + isProcessRestarted = true; + } + isActivateRequest = true; + isDeactivateRequest = false; + break; + case score::lcm::SupervisionEventType::kDeactivation: + isDeactivateRequest = true; + break; } } diff --git a/score/launch_manager/src/daemon/src/configuration/BUILD b/score/launch_manager/src/daemon/src/configuration/BUILD index 4329824b7a..3875e15836 100644 --- a/score/launch_manager/src/daemon/src/configuration/BUILD +++ b/score/launch_manager/src/daemon/src/configuration/BUILD @@ -133,9 +133,9 @@ cc_library( "//score/launch_manager/src/daemon/src/common:identifier_hash", "//score/launch_manager/src/daemon/src/common:log", "//score/launch_manager/src/daemon/src/common:process_group_state_id", + "//score/launch_manager/src/daemon/src/common:process_state", "//score/launch_manager/src/daemon/src/osal:num_cores", "//score/launch_manager/src/daemon/src/process_group_manager:iprocess", - "//score/launch_manager/src/daemon/src/common:process_state", ], ) @@ -145,9 +145,9 @@ lm_cc_test( visibility = ["//tests:__subpackages__"], deps = [ ":configuration_adapter", + "//score/launch_manager/src/daemon/src/common:process_state", "//score/launch_manager/src/daemon/src/osal:num_cores", "//score/launch_manager/src/daemon/src/process_group_manager:iprocess", - "//score/launch_manager/src/daemon/src/common:process_state", "@googletest//:gtest_main", "@score_baselibs//score/flatbuffers:flatbufferscpp", ], diff --git a/score/launch_manager/src/daemon/src/process_group_manager/BUILD b/score/launch_manager/src/daemon/src/process_group_manager/BUILD index 84199230de..50acc97bfe 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/BUILD +++ b/score/launch_manager/src/daemon/src/process_group_manager/BUILD @@ -82,8 +82,8 @@ cc_library( "//score/launch_manager/src/daemon/src/process_group_manager/details:process_launcher", "//score/launch_manager/src/daemon/src/process_group_manager/details:process_monitor", "//score/launch_manager/src/daemon/src/process_group_manager/details:safe_process_map", - "//score/launch_manager/src/daemon/src/supervision_control_client:isupervision_control_notifier", "//score/launch_manager/src/daemon/src/recovery_client", + "//score/launch_manager/src/daemon/src/supervision_control_client:isupervision_control_notifier", "//score/launch_manager/src/daemon/src/watchdog:i_watchdog_if", "@score_baselibs//score/language/futurecpp", ], diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp index 5fcbf7f0e3..94497b5c6d 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp @@ -88,8 +88,10 @@ IComponent::RequestResult ProcessInfoNode::tryReportSuccess() return {IComponent::RequestState::kWaiting}; } -std::optional ProcessInfoNode::getTimeForReport() const { - if (config_->startup_config_.comms_type_ == osal::CommsType::kNoComms) { +std::optional ProcessInfoNode::getTimeForReport() const +{ + if (config_->startup_config_.comms_type_ == osal::CommsType::kNoComms) + { return std::nullopt; } diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/BUILD b/score/launch_manager/src/daemon/src/supervision_control_client/BUILD index 8f3ec34f1e..6182bd9af9 100644 --- a/score/launch_manager/src/daemon/src/supervision_control_client/BUILD +++ b/score/launch_manager/src/daemon/src/supervision_control_client/BUILD @@ -44,8 +44,8 @@ cc_library( visibility = ["//score:__subpackages__"], deps = [ ":isupervision_control_receiver", + ":isupervision_event_publisher", ":supervision_event", - ":isupervision_event_publisher" ], ) @@ -62,8 +62,8 @@ cc_library( cc_library( name = "mock_supervision_event_publisher", - hdrs = ["mock_supervision_event_publisher.hpp"], testonly = True, + hdrs = ["mock_supervision_event_publisher.hpp"], include_prefix = "score/mw/launch_manager/supervision_control_client", strip_include_prefix = "/score/launch_manager/src/daemon/src/supervision_control_client", visibility = ["//score:__subpackages__"], From adb32136aed258aa7f07a9212d4f90df09d399c4 Mon Sep 17 00:00:00 2001 From: William Roebuck <244554584+WilliamRoebuck@users.noreply.github.com> Date: Fri, 7 Aug 2026 10:50:56 +0100 Subject: [PATCH 05/13] Fix tsan failure --- .../supervision_control_client_ut.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp index d1e6a1bd8f..0bb7c74271 100644 --- a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp +++ b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp @@ -131,5 +131,8 @@ TEST_F(SupervisionControlClient_UT, SupervisionControlClient_QueueOneEventTooMan auto result = receiver_->getNextSupervisionEvent(); ASSERT_FALSE(result.has_value()) << "Expected no events to be retrievable"; - EXPECT_EQ(result.error(), score::mw::lifecycle::ExecErrc::kCommunicationError); + + EXPECT_EQ( + static_cast(*result.error()), + score::mw::lifecycle::ExecErrc::kCommunicationError); } From 91560a1b1d879ff3bbebd28867554cf7ee46e6bd Mon Sep 17 00:00:00 2001 From: William Roebuck <244554584+WilliamRoebuck@users.noreply.github.com> Date: Fri, 7 Aug 2026 14:45:40 +0100 Subject: [PATCH 06/13] Changes after review --- score/launch_manager/src/daemon/src/common/process_state.hpp | 2 +- .../src/daemon/src/supervision_control_client/BUILD | 5 +++-- .../supervision_control_client_ut.cpp | 3 +++ .../src/supervision_control_client/supervision_event.hpp | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/score/launch_manager/src/daemon/src/common/process_state.hpp b/score/launch_manager/src/daemon/src/common/process_state.hpp index 95a622d7e6..a733670664 100644 --- a/score/launch_manager/src/daemon/src/common/process_state.hpp +++ b/score/launch_manager/src/daemon/src/common/process_state.hpp @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation + * Copyright (c) 2026 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/BUILD b/score/launch_manager/src/daemon/src/supervision_control_client/BUILD index 6182bd9af9..26c77445a1 100644 --- a/score/launch_manager/src/daemon/src/supervision_control_client/BUILD +++ b/score/launch_manager/src/daemon/src/supervision_control_client/BUILD @@ -10,7 +10,8 @@ # # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") +load("@rules_cc//cc:defs.bzl", "cc_library") +load("//tests/utils/bazel:unit_test.bzl", "lm_cc_test") cc_library( name = "supervision_event", @@ -97,7 +98,7 @@ cc_library( ], ) -cc_test( +lm_cc_test( name = "supervision_control_client_ut", srcs = ["supervision_control_client_ut.cpp"], deps = [ diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp index 0bb7c74271..86150a8001 100644 --- a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp +++ b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_client_ut.cpp @@ -61,6 +61,8 @@ TEST_F(SupervisionControlClient_UT, SupervisionControlClient_QueueOneEvent_Succe .eventType = score::lcm::SupervisionEventType::kActivation, .systemClockTimestamp = {}}; + clock_gettime(CLOCK_MONOTONIC, &event1.systemClockTimestamp); + bool queued = notifier_->reportActivation(event1.id, event1.systemClockTimestamp); ASSERT_TRUE(queued); @@ -69,6 +71,7 @@ TEST_F(SupervisionControlClient_UT, SupervisionControlClient_QueueOneEvent_Succe ASSERT_TRUE(result->has_value()); EXPECT_EQ(result->value().id, event1.id); EXPECT_EQ(result->value().eventType, event1.eventType); + EXPECT_EQ(result->value().systemClockTimestamp.tv_nsec, event1.systemClockTimestamp.tv_nsec); auto no_more = receiver_->getNextSupervisionEvent(); ASSERT_TRUE(no_more.has_value()); diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_event.hpp b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_event.hpp index 2ef7f74213..1d5eda09f9 100644 --- a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_event.hpp +++ b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_event.hpp @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation + * Copyright (c) 2026 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. From 2c2e5dba8884369bc0fccd96b06adf9e05baf87a Mon Sep 17 00:00:00 2001 From: William Roebuck <244554584+WilliamRoebuck@users.noreply.github.com> Date: Mon, 10 Aug 2026 12:57:35 +0100 Subject: [PATCH 07/13] Cleanup --- .../details/supervision_control_receiver.hpp | 8 ++++---- .../supervision_control_notifier.hpp | 2 ++ .../supervision_event.hpp | 20 +++++++++++-------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/details/supervision_control_receiver.hpp b/score/launch_manager/src/daemon/src/supervision_control_client/details/supervision_control_receiver.hpp index 3693f408a5..02839d8967 100644 --- a/score/launch_manager/src/daemon/src/supervision_control_client/details/supervision_control_receiver.hpp +++ b/score/launch_manager/src/daemon/src/supervision_control_client/details/supervision_control_receiver.hpp @@ -23,14 +23,14 @@ namespace score namespace lcm { -using BufferP = std::shared_ptr(score::lcm::BufferConstants::BUFFER_QUEUE_SIZE), - static_cast(score::lcm::BufferConstants::BUFFER_MAXPAYLOAD)>>; - /// @brief SupervisionControlReceiver implementation for receiving supervision events from the Launch Manager. class SupervisionControlReceiver final : public ISupervisionControlReceiver { public: + using BufferP = std::shared_ptr(score::lcm::BufferConstants::BUFFER_QUEUE_SIZE), + static_cast(score::lcm::BufferConstants::BUFFER_MAXPAYLOAD)>>; + /// @brief Constructor that creates the SupervisionControlReceiver /// @param ring_buffer Shared pointer to the ring buffer used to receive supervision events SupervisionControlReceiver(BufferP ring_buffer) noexcept; diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.hpp b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.hpp index 39c6d739bc..a6ad01ec69 100644 --- a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.hpp +++ b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_control_notifier.hpp @@ -55,8 +55,10 @@ class SupervisionControlNotifier final : public ISupervisionControlNotifier /// @return Supervision control receiver instance std::unique_ptr constructReceiver() override; + /// @brief Report that process with @param id has reached the active state at @param time bool reportActivation(IdentifierHash id, timespec time) noexcept override; + /// @brief Report that process with @param id has changed from the active state at @param time bool reportDeactivation(IdentifierHash id, timespec time) noexcept override; private: diff --git a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_event.hpp b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_event.hpp index 1d5eda09f9..9a329ec60a 100644 --- a/score/launch_manager/src/daemon/src/supervision_control_client/supervision_event.hpp +++ b/score/launch_manager/src/daemon/src/supervision_control_client/supervision_event.hpp @@ -27,12 +27,12 @@ namespace lcm /// @brief Type of supervision event sent from the launch manager to the alive monitor. enum class SupervisionEventType : std::uint8_t { - kActivation = 0, ///< Supervision should be activated (process reached running state). - kDeactivation = 1 ///< Supervision should be deactivated (process terminating or terminated). + /// @brief Supervision should be activated (process reached running state). + kActivation = 0, + /// @brief Supervision should be deactivated (process terminating or terminated). + kDeactivation = 1 }; -// RULECHECKER_comment(1, 1, check_incomplete_data_member_construction, "This struct is POD, which doesn't have -// user-declared constructor. The rule doesn't apply.", false) struct SupervisionEvent { /// @brief Stores the Modelled Process ID as IdentifierHash. @@ -45,11 +45,15 @@ struct SupervisionEvent timespec systemClockTimestamp; }; -enum class BufferConstants : size_t +namespace BufferConstants { - BUFFER_MAXPAYLOAD = sizeof(SupervisionEvent), ///< Ringbuffer max payload size - BUFFER_QUEUE_SIZE = 4096UL ///< Ringbuffer queue size -}; + +/// @brief Ringbuffer max payload size +constexpr std::size_t BUFFER_MAXPAYLOAD = sizeof(SupervisionEvent); +/// @brief Ringbuffer queue size +constexpr std::size_t BUFFER_QUEUE_SIZE = 4096UL; + +} // namespace BufferConstants } // namespace lcm From 815564f9917d90202086bd71cb0a35d50197ed9f Mon Sep 17 00:00:00 2001 From: William Roebuck <244554584+WilliamRoebuck@users.noreply.github.com> Date: Mon, 10 Aug 2026 13:09:22 +0100 Subject: [PATCH 08/13] Move process_state.hpp --- .../launch_manager/src/daemon/src/common/BUILD | 8 -------- .../src/daemon/src/configuration/BUILD | 4 ++-- .../src/configuration/configuration_adapter.hpp | 2 +- .../src/daemon/src/process_group_manager/BUILD | 17 +++++++++++++++++ .../process_state.hpp | 0 5 files changed, 20 insertions(+), 11 deletions(-) rename score/launch_manager/src/daemon/src/{common => process_group_manager}/process_state.hpp (100%) diff --git a/score/launch_manager/src/daemon/src/common/BUILD b/score/launch_manager/src/daemon/src/common/BUILD index 81345f6491..78ae20afb5 100644 --- a/score/launch_manager/src/daemon/src/common/BUILD +++ b/score/launch_manager/src/daemon/src/common/BUILD @@ -98,14 +98,6 @@ cc_library( visibility = ["//score:__subpackages__"], ) -cc_library( - name = "process_state", - hdrs = ["process_state.hpp"], - include_prefix = "score/mw/launch_manager/common", - strip_include_prefix = "/score/launch_manager/src/daemon/src/common", - visibility = ["//score:__subpackages__"], -) - cc_library( name = "process_group_state_id", hdrs = [ diff --git a/score/launch_manager/src/daemon/src/configuration/BUILD b/score/launch_manager/src/daemon/src/configuration/BUILD index 3875e15836..fcc6a550d3 100644 --- a/score/launch_manager/src/daemon/src/configuration/BUILD +++ b/score/launch_manager/src/daemon/src/configuration/BUILD @@ -133,7 +133,7 @@ cc_library( "//score/launch_manager/src/daemon/src/common:identifier_hash", "//score/launch_manager/src/daemon/src/common:log", "//score/launch_manager/src/daemon/src/common:process_group_state_id", - "//score/launch_manager/src/daemon/src/common:process_state", + "//score/launch_manager/src/daemon/src/process_group_manager:process_state", "//score/launch_manager/src/daemon/src/osal:num_cores", "//score/launch_manager/src/daemon/src/process_group_manager:iprocess", ], @@ -145,7 +145,7 @@ lm_cc_test( visibility = ["//tests:__subpackages__"], deps = [ ":configuration_adapter", - "//score/launch_manager/src/daemon/src/common:process_state", + "//score/launch_manager/src/daemon/src/process_group_manager:process_state", "//score/launch_manager/src/daemon/src/osal:num_cores", "//score/launch_manager/src/daemon/src/process_group_manager:iprocess", "@googletest//:gtest_main", diff --git a/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp b/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp index 00beaf7bc5..7517a0d0d0 100644 --- a/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp +++ b/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp @@ -17,7 +17,7 @@ #include "score/mw/launch_manager/common/constants.hpp" #include "score/mw/launch_manager/common/identifier_hash.hpp" #include "score/mw/launch_manager/common/process_group_state_id.hpp" -#include "score/mw/launch_manager/common/process_state.hpp" +#include "score/mw/launch_manager/process_group_manager/process_state.hpp" #include "score/mw/launch_manager/configuration/config.hpp" #include "score/mw/launch_manager/process_group_manager/iprocess.hpp" #include diff --git a/score/launch_manager/src/daemon/src/process_group_manager/BUILD b/score/launch_manager/src/daemon/src/process_group_manager/BUILD index 50acc97bfe..bc08083b66 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/BUILD +++ b/score/launch_manager/src/daemon/src/process_group_manager/BUILD @@ -88,3 +88,20 @@ cc_library( "@score_baselibs//score/language/futurecpp", ], ) + +cc_library( + name = "process_group_manager", + visibility = ["//score:__subpackages__"], + deps = [ + ":process_group_manager_hdrs", + "//score/launch_manager/src/daemon/src/process_group_manager/details:process_group_manager_impl", + ], +) + +cc_library( + name = "process_state", + hdrs = ["process_state.hpp"], + include_prefix = "score/mw/launch_manager/process_group_manager", + strip_include_prefix = "/score/launch_manager/src/daemon/src/process_group_manager", + visibility = ["//score:__subpackages__"], +) \ No newline at end of file diff --git a/score/launch_manager/src/daemon/src/common/process_state.hpp b/score/launch_manager/src/daemon/src/process_group_manager/process_state.hpp similarity index 100% rename from score/launch_manager/src/daemon/src/common/process_state.hpp rename to score/launch_manager/src/daemon/src/process_group_manager/process_state.hpp From f2a3506c7ec9358ac45b453c5e5cfd6557adae14 Mon Sep 17 00:00:00 2001 From: William Roebuck <244554584+WilliamRoebuck@users.noreply.github.com> Date: Mon, 10 Aug 2026 13:27:58 +0100 Subject: [PATCH 09/13] Update missed names --- .../daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp | 2 +- .../src/alive_monitor/details/ifexm/ProcessStateReader.cpp | 2 +- .../src/alive_monitor/details/ifexm/ProcessStateReader.hpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp index c388745764..ba3595c771 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp @@ -53,7 +53,7 @@ class PhmDaemon { public: using OsClock = score::lcm::saf::timers::OsClockInterface; - using ProcessStateReceiver = score::lcm::ISupervisionControlReceiver; + using SupervisionControlReceiver = score::lcm::ISupervisionControlReceiver; using RecoveryClient = score::lcm::IRecoveryClient; using SupervisionBufferConfig = factory::SupervisionBufferConfig; using CycleTimer = score::lcm::saf::timers::CycleTimer; diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.cpp index 14683aceef..aa049a57ad 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.cpp @@ -24,7 +24,7 @@ namespace saf namespace ifexm { -ProcessStateReader::ProcessStateReader(std::unique_ptr f_process_state_receiver) +ProcessStateReader::ProcessStateReader(std::unique_ptr f_process_state_receiver) : processStateReceiverHM(std::move(f_process_state_receiver)) { } diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.hpp index 3845917cd3..420854f4f8 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/ifexm/ProcessStateReader.hpp @@ -38,11 +38,11 @@ class ProcessStateReader { public: using LcmSupervisionEvent = score::lcm::SupervisionEvent; - using LcmProcessStateReceiver = score::lcm::ISupervisionControlReceiver; + using LcmSupervisionControlReceiver = score::lcm::ISupervisionControlReceiver; /// @brief Constructor /// @param [in] f_process_state_receiver Process state receiver implementation - ProcessStateReader(std::unique_ptr f_process_state_receiver); + ProcessStateReader(std::unique_ptr f_process_state_receiver); /// @brief No Copy Constructor ProcessStateReader(const ProcessStateReader&) = delete; @@ -80,7 +80,7 @@ class ProcessStateReader bool pushUpdateTill(const LcmSupervisionEvent& f_event, const timers::NanoSecondType f_syncTimestamp) noexcept; /// @brief Process state receiver for HM thread - std::unique_ptr processStateReceiverHM; + std::unique_ptr processStateReceiverHM; /// @brief Map for process id and process state object std::map processStateMap{}; From f1326bb620b389ea27a93e8eddc5ac7d96beca24 Mon Sep 17 00:00:00 2001 From: William Roebuck <244554584+WilliamRoebuck@users.noreply.github.com> Date: Mon, 10 Aug 2026 15:03:33 +0100 Subject: [PATCH 10/13] Fixes after rebase --- .../src/daemon/src/process_group_manager/BUILD | 9 --------- .../src/process_group_manager/details/graph_UT.cpp | 1 - 2 files changed, 10 deletions(-) diff --git a/score/launch_manager/src/daemon/src/process_group_manager/BUILD b/score/launch_manager/src/daemon/src/process_group_manager/BUILD index bc08083b66..d6f5f4bbe9 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/BUILD +++ b/score/launch_manager/src/daemon/src/process_group_manager/BUILD @@ -89,15 +89,6 @@ cc_library( ], ) -cc_library( - name = "process_group_manager", - visibility = ["//score:__subpackages__"], - deps = [ - ":process_group_manager_hdrs", - "//score/launch_manager/src/daemon/src/process_group_manager/details:process_group_manager_impl", - ], -) - cc_library( name = "process_state", hdrs = ["process_state.hpp"], diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp index 8f9fd80394..a2725d5c3c 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp @@ -17,7 +17,6 @@ #include "score/mw/launch_manager/configuration/configuration_adapter.hpp" #include "score/mw/launch_manager/process_group_manager/details/graph.hpp" #include "score/mw/launch_manager/process_group_manager/mock_iprocess.hpp" -#include "score/mw/launch_manager/process_group_manager/process_group_manager.hpp" #include "score/mw/launch_manager/supervision_control_client/mock_supervision_event_publisher.hpp" namespace score::lcm::internal From 61f09f638d5b5e1c5f0bc6ce219d9e54caf5f142 Mon Sep 17 00:00:00 2001 From: William Roebuck <244554584+WilliamRoebuck@users.noreply.github.com> Date: Mon, 10 Aug 2026 16:55:20 +0100 Subject: [PATCH 11/13] Remove regressed member --- .../daemon/src/process_group_manager/process_group_manager.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.hpp b/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.hpp index 765ffc511f..38654db31b 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.hpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.hpp @@ -309,9 +309,6 @@ class ProcessGroupManager final : public ITransitionResultPublisher /// @brief Process state notifier object used to send data to PHM std::unique_ptr supervision_control_notifier_; - /// @brief pointer to the configuration for Launch Manager - const OsProcess* launch_manager_config_{nullptr}; - std::unique_ptr alive_monitor_thread_; std::unique_ptr process_monitor_; From 8d8a9bfce333056c05d2090411207eb2675ead9c Mon Sep 17 00:00:00 2001 From: William Roebuck <244554584+WilliamRoebuck@users.noreply.github.com> Date: Tue, 11 Aug 2026 09:27:38 +0100 Subject: [PATCH 12/13] Make notifier a reference --- .../src/daemon/src/process_group_manager/details/graph.cpp | 2 +- .../src/daemon/src/process_group_manager/details/graph.hpp | 4 ++-- .../daemon/src/process_group_manager/details/graph_UT.cpp | 2 +- .../src/process_group_manager/details/process_info_node.cpp | 6 +++--- .../src/process_group_manager/details/process_info_node.hpp | 5 +++-- .../process_group_manager/details/process_info_node_UT.cpp | 2 +- .../src/process_group_manager/process_group_manager.cpp | 2 +- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp index 7090cc46f2..59b686924b 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.cpp @@ -39,7 +39,7 @@ Graph::Graph( std::shared_ptr job_queue, osal::IProcess* process_interface, std::shared_ptr process_map, - ISupervisionEventPublisher* supervision_event_publisher, + ISupervisionEventPublisher& supervision_event_publisher, ITransitionResultPublisher* transition_result_receiver) : pg_index_(0U), nodes_(max_num_nodes), diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.hpp b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.hpp index 382c0eae5b..0308c0cc87 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/graph.hpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/graph.hpp @@ -156,7 +156,7 @@ class Graph final std::shared_ptr job_queue, osal::IProcess* process_interface, std::shared_ptr process_map, - ISupervisionEventPublisher* supervision_event_publisher, + ISupervisionEventPublisher& supervision_event_publisher, ITransitionResultPublisher* transition_result_receiver); /// @brief Destructor to clean up resources used by the Graph object. @@ -390,7 +390,7 @@ class Graph final std::shared_ptr process_map_; /// @brief Interface to pass process nodes for alive monitor notifications - ISupervisionEventPublisher* supervision_event_publisher_; + ISupervisionEventPublisher& supervision_event_publisher_; /// @brief Class to receive information about the initial state transition result ITransitionResultPublisher* transition_result_receiver_; diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp index a2725d5c3c..1ef8cb268c 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/graph_UT.cpp @@ -188,7 +188,7 @@ class GraphTest : public ::testing::Test job_queue_, &process_interface_, mock_process_map, - &mock_supervision_event_publisher_, + mock_supervision_event_publisher_, &mock_transition_result_publisher_}; static constexpr std::string_view pg_string{"MainPG"}; diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp index 94497b5c6d..7a6fae1662 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp @@ -31,7 +31,7 @@ ProcessInfoNode::ProcessInfoNode( const OsProcess* config, uint32_t index, ReadyCondition ready_condition, - ISupervisionEventPublisher* state_publisher, + ISupervisionEventPublisher& state_publisher, osal::IProcess* process_interface, std::shared_ptr process_map) : terminator_(), @@ -80,7 +80,7 @@ IComponent::RequestResult ProcessInfoNode::tryReportSuccess() if (auto time = getTimeForReport()) { - state_publisher_->reportActivation(config_->process_id_, time.value()); + state_publisher_.reportActivation(config_->process_id_, time.value()); } return {RequestState::kSuccess}; @@ -416,7 +416,7 @@ IComponent::RequestResult ProcessInfoNode::deactivate(score::cpp::stop_token sto reached_ready_.store(false); if (auto time = getTimeForReport()) { - state_publisher_->reportDeactivation(config_->process_id_, time.value()); + state_publisher_.reportDeactivation(config_->process_id_, time.value()); } terminateProcess(stop_token); setState(ProcessState::kIdle); diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp index 26b490dfe1..4a8395750d 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp @@ -63,7 +63,7 @@ class ProcessInfoNode final : public IComponent const OsProcess* config, uint32_t index, ReadyCondition ready_condition, - ISupervisionEventPublisher* state_publisher, + ISupervisionEventPublisher& state_publisher, osal::IProcess* process_interface, std::shared_ptr process_map); @@ -80,6 +80,7 @@ class ProcessInfoNode final : public IComponent config_(other.config_), control_client_channel_(std::move(other.control_client_channel_)), sync_(std::move(other.sync_)), + state_publisher_(other.state_publisher_), process_interface_(other.process_interface_), process_map_(std::move(other.process_map_)) { @@ -206,7 +207,7 @@ class ProcessInfoNode final : public IComponent osal::IpcCommsP sync_{nullptr}; /// @brief Interface for reporting component state to health monitor - ISupervisionEventPublisher* state_publisher_; + ISupervisionEventPublisher& state_publisher_; /// @brief True if we have returned a success or failure for the current activation/deactivation std::atomic_flag success_returned_{false}; diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node_UT.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node_UT.cpp index 414fdcb2b4..c745513f0c 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node_UT.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node_UT.cpp @@ -60,7 +60,7 @@ class ProcessInfoNodeFixture : public ::testing::Test config_.pgm_config_ = pgm_config; return std::make_unique( - &config_, kProcessIndex, ready_condition, &mock_publisher_, &mock_processIf_, process_map_); + &config_, kProcessIndex, ready_condition, mock_publisher_, &mock_processIf_, process_map_); } /// @brief Helper method to create a ProcessInfoNode that is self-terminating. diff --git a/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.cpp b/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.cpp index 6d28fc2199..9da7b14356 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/process_group_manager.cpp @@ -245,7 +245,7 @@ bool ProcessGroupManager::initializeProcessGroups() worker_jobs_, &process_interface_, process_map_, - supervision_control_notifier_.get(), + *supervision_control_notifier_.get(), this)); } } From 7ffd92e56533598d037c4ec8a9d2130e91f43151 Mon Sep 17 00:00:00 2001 From: William Roebuck <244554584+WilliamRoebuck@users.noreply.github.com> Date: Tue, 11 Aug 2026 10:14:36 +0100 Subject: [PATCH 13/13] Fix format --- score/launch_manager/src/daemon/src/configuration/BUILD | 4 ++-- .../src/daemon/src/configuration/configuration_adapter.hpp | 2 +- .../launch_manager/src/daemon/src/process_group_manager/BUILD | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/score/launch_manager/src/daemon/src/configuration/BUILD b/score/launch_manager/src/daemon/src/configuration/BUILD index fcc6a550d3..c48393628e 100644 --- a/score/launch_manager/src/daemon/src/configuration/BUILD +++ b/score/launch_manager/src/daemon/src/configuration/BUILD @@ -133,9 +133,9 @@ cc_library( "//score/launch_manager/src/daemon/src/common:identifier_hash", "//score/launch_manager/src/daemon/src/common:log", "//score/launch_manager/src/daemon/src/common:process_group_state_id", - "//score/launch_manager/src/daemon/src/process_group_manager:process_state", "//score/launch_manager/src/daemon/src/osal:num_cores", "//score/launch_manager/src/daemon/src/process_group_manager:iprocess", + "//score/launch_manager/src/daemon/src/process_group_manager:process_state", ], ) @@ -145,9 +145,9 @@ lm_cc_test( visibility = ["//tests:__subpackages__"], deps = [ ":configuration_adapter", - "//score/launch_manager/src/daemon/src/process_group_manager:process_state", "//score/launch_manager/src/daemon/src/osal:num_cores", "//score/launch_manager/src/daemon/src/process_group_manager:iprocess", + "//score/launch_manager/src/daemon/src/process_group_manager:process_state", "@googletest//:gtest_main", "@score_baselibs//score/flatbuffers:flatbufferscpp", ], diff --git a/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp b/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp index 7517a0d0d0..325a829c3e 100644 --- a/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp +++ b/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp @@ -17,9 +17,9 @@ #include "score/mw/launch_manager/common/constants.hpp" #include "score/mw/launch_manager/common/identifier_hash.hpp" #include "score/mw/launch_manager/common/process_group_state_id.hpp" -#include "score/mw/launch_manager/process_group_manager/process_state.hpp" #include "score/mw/launch_manager/configuration/config.hpp" #include "score/mw/launch_manager/process_group_manager/iprocess.hpp" +#include "score/mw/launch_manager/process_group_manager/process_state.hpp" #include #include #include diff --git a/score/launch_manager/src/daemon/src/process_group_manager/BUILD b/score/launch_manager/src/daemon/src/process_group_manager/BUILD index d6f5f4bbe9..4f1ba54df3 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/BUILD +++ b/score/launch_manager/src/daemon/src/process_group_manager/BUILD @@ -95,4 +95,4 @@ cc_library( include_prefix = "score/mw/launch_manager/process_group_manager", strip_include_prefix = "/score/launch_manager/src/daemon/src/process_group_manager", visibility = ["//score:__subpackages__"], -) \ No newline at end of file +)