Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions examples/c_supervised_app/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# *******************************************************************************
# 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_binary")

cc_binary(
name = "c_supervised_app",
srcs = [
"main.c",
],
linkopts = select({
"@platforms//os:qnx": [
"-lsocket",
],
"@platforms//os:linux": [
"-lpthread",
"-lrt",
],
}),
visibility = ["//visibility:public"],
deps = [
"//score/launch_manager:alive_cc",
"//score/launch_manager:lifecycle_cc",
],
)
59 changes: 59 additions & 0 deletions examples/c_supervised_app/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/********************************************************************************
* 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 <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <score/mw/lifecycle/alive.h>
#include <score/mw/lifecycle/report_running.h>

static volatile sig_atomic_t exit_requested = 0;

static void signal_handler(int signal)
{
if (signal == SIGINT || signal == SIGTERM)
{
exit_requested = 1;
}
}

int main(void)
{
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);

void* alive = score_lcm_alive_initialize("/example/instance");
if (alive == NULL)
{
fprintf(stderr, "Failed to initialize alive instance\n");
return EXIT_FAILURE;
}

if (score_lcm_ReportRunning() != 0)
{
fprintf(stderr, "Failed to report running state\n");
score_lcm_alive_deinitialize(alive);
return EXIT_FAILURE;
}

while (!exit_requested)
{
score_lcm_alive_report_alive(alive);
usleep(50000);
}

score_lcm_alive_deinitialize(alive);
return EXIT_SUCCESS;
}
1 change: 1 addition & 0 deletions examples/demo_verification/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ launch_manager_config(
pkg_files(
name = "examples_main_files",
srcs = [
"//examples/c_supervised_app",
"//examples/control_application:control_daemon",
"//examples/control_application:lmcontrol",
"//examples/cpp_lifecycle_app",
Expand Down
15 changes: 15 additions & 0 deletions examples/demo_verification/lifecycle_demo_test.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,20 @@
}
}
},
"c_supervised_app": {
"component_properties": {
"binary_name": "c_supervised_app",
"application_profile": {
"application_type": "Reporting_And_Supervised"
}
},
"deployment_config": {
"environmental_variables": {
"PROCESSIDENTIFIER": "c_supervised_app",
"IDENTIFIER": "c_supervised_app"
}
}
},
"lifecycle_app": {
"component_properties": {
"binary_name": "cpp_lifecycle_app"
Expand Down Expand Up @@ -121,6 +135,7 @@
"control_daemon",
"cpp_supervised_app",
"rust_supervised_app",
"c_supervised_app",
"lifecycle_app"
],
"recovery_action": {
Expand Down
7 changes: 6 additions & 1 deletion examples/demo_verification/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@
from tests.utils.testing_utils.setup_test import setup_test
from attribute_plugin import add_test_properties

_DEMO_APPS = ("cpp_supervised_app", "rust_supervised_app", "cpp_lifecycle_app")
_DEMO_APPS = (
"cpp_supervised_app",
"rust_supervised_app",
"cpp_lifecycle_app",
"c_supervised_app",
)


def _assert_running(target, *binaries):
Expand Down
31 changes: 17 additions & 14 deletions score/launch_manager/src/alive/src/alive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,16 @@
#include "score/mw/lifecycle/alive.h"
#include "score/mw/launch_manager/alive_monitor/details/AliveImpl.h"

#include <utility>
#include <cassert>
#include <utility>

// The public API is only sending alive notification. No need to support different checkpoints.
static constexpr std::uint32_t kDefaultCheckpointId{1U};

namespace score::mw::lifecycle
{

Alive::Alive(const std::string_view& instance) noexcept(false) :
aliveImplPtr(std::make_unique<AliveImpl>(instance))
{
}
Alive::Alive(const std::string_view& instance) noexcept(false) : aliveImplPtr(std::make_unique<AliveImpl>(instance)) {}

Alive::Alive(Alive&& se) noexcept = default;

Expand All @@ -49,41 +46,47 @@ void Alive::ReportFailure() const noexcept

} // namespace score::mw::lifecycle


#ifdef __cplusplus
extern "C" {
#endif

void* score_lcm_alive_initialize(const char* instanceSpecifier) noexcept {
if(instanceSpecifier == nullptr) {
void* score_lcm_alive_initialize(const char* instanceSpecifier)
{
if (instanceSpecifier == nullptr)
{
return nullptr;
}

try {
try
{
auto* alivePtr = new score::mw::lifecycle::Alive(instanceSpecifier);
return static_cast<void*>(alivePtr);
} catch (...) {
}
catch (...)
{
return nullptr;
}
}

void score_lcm_alive_deinitialize(void* instance) noexcept {
void score_lcm_alive_deinitialize(void* instance)
{
SCORE_LANGUAGE_FUTURECPP_PRECONDITION(instance != nullptr);
auto* alivePtr = static_cast<score::mw::lifecycle::Alive*>(instance);
delete alivePtr;
}

void score_lcm_alive_report_alive(void* instance) noexcept {
void score_lcm_alive_report_alive(void* instance)
{
SCORE_LANGUAGE_FUTURECPP_PRECONDITION(instance != nullptr);
static_cast<score::mw::lifecycle::Alive*>(instance)->ReportAlive();
}

void score_lcm_alive_report_failure(void* instance) noexcept {
void score_lcm_alive_report_failure(void* instance)
{
SCORE_LANGUAGE_FUTURECPP_PRECONDITION(instance != nullptr);
static_cast<score::mw::lifecycle::Alive*>(instance)->ReportFailure();
}


#ifdef __cplusplus
}
#endif
37 changes: 33 additions & 4 deletions score/launch_manager/src/alive/src/alive.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#ifndef SCORE_LCM_ALIVE_H_
#define SCORE_LCM_ALIVE_H_

#ifdef __cplusplus
#include <cstdint>
#include <memory>
#include <string_view>
Expand All @@ -26,14 +27,14 @@ class AliveImpl;

/// @brief Alive API for reporting alive notifications to the launch manager.
/// An alive notification indicates that the component is still active and functioning correctly.
/// The launch manager is configured with an expected alive notification interval,
/// and if it does not receive an alive notification within that interval,
/// The launch manager is configured with an expected alive notification interval,
/// and if it does not receive an alive notification within that interval,
/// it executes the configured recovery action.
///
/// Each process may only use a single Alive instance.
class Alive
{
public:
public:
/// @brief Creation of an Alive.
/// @param [in] instance Instance specifier (currently unused)
/// @throws std::runtime_error if the configured IPC channel to connect to launch manager is not existing
Expand Down Expand Up @@ -67,10 +68,38 @@ class Alive
/// @note Not Implemented. This method currently does nothing.
void ReportFailure() const noexcept;

private:
private:
/// @brief Unique pointer to implementation class of Alive
std::unique_ptr<AliveImpl> aliveImplPtr;
};

} // namespace score::mw::lifecycle

extern "C" {
#endif /* __cplusplus */

// These prototypes are required to support applications written in C, which cannot use the C++ namespaces and classes.

/// @brief Initialize an Alive instance.
/// @param [in] instanceSpecifier Instance specifier string (must not be NULL)
/// @return Opaque pointer to the Alive instance, or NULL on failure
void* score_lcm_alive_initialize(const char* instanceSpecifier);

/// @brief Deinitialize (destroy) an Alive instance.
/// @param [in] instance Opaque pointer previously returned by score_lcm_alive_initialize (must not be NULL)
void score_lcm_alive_deinitialize(void* instance);

/// @brief Report an alive notification.
/// @param [in] instance Opaque pointer previously returned by score_lcm_alive_initialize (must not be NULL)
void score_lcm_alive_report_alive(void* instance);

/// @brief Report a direct failure.
/// @param [in] instance Opaque pointer previously returned by score_lcm_alive_initialize (must not be NULL)
/// @note Not Implemented. This method currently does nothing.
void score_lcm_alive_report_failure(void* instance);

#ifdef __cplusplus
}
#endif

#endif // SCORE_LCM_ALIVE_H_
34 changes: 27 additions & 7 deletions score/launch_manager/src/lifecycle_client/src/report_running.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,16 @@
#ifndef SCORE_MW_LIFECYCLE_REPORT_RUNNING_H_
#define SCORE_MW_LIFECYCLE_REPORT_RUNNING_H_

namespace score {
namespace mw {
namespace lifecycle {
#include <stdint.h>

#ifdef __cplusplus

namespace score
{
namespace mw
{
namespace lifecycle
{

/// @brief Signals to the Launch Manager that this process has finished
/// initialization and is now entering its Running state.
Expand All @@ -36,8 +43,21 @@ namespace lifecycle {
/// shutdown accordingly.
void report_running() noexcept;

} // namespace lifecycle
} // namespace mw
} // namespace score
} // namespace lifecycle
} // namespace mw
} // namespace score

extern "C" {
#endif /* __cplusplus */

// This prototype is required to support applications written in C, which cannot use the C++ namespaces and classes.

/// @brief Signals to the Launch Manager that this process has finished initialization and is now running.
/// @return 0 on success, -1 on failure
int8_t score_lcm_ReportRunning(void);

#ifdef __cplusplus
}
#endif

#endif
#endif /* SCORE_MW_LIFECYCLE_REPORT_RUNNING_H_ */
Loading