|
Safe API Framework
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
|
Application Manager implementation. More...
#include <stdbool.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "safeapi/app/appmanager/sapi_appmanager.h"#include "safeapi/redundancy/checksum/sapi_checksum.h"#include "safeapi/redundancy/checkpoint/sapi_checkpoint.h"#include "safeapi/utils/lifecycle/sapi_lifecycle.h"#include "safeapi/oal/log/sapi_log.h"#include "safeapi/oal/timer/sapi_timer.h"Go to the source code of this file.
Macros | |
| #define | _POSIX_C_SOURCE 200809L |
| struct sigaction/sigaction()/sigemptyset() below are POSIX.1-2001, not base ISO C99 - must be defined before ANY header is included (same rule/pattern as safeAPIRBC2oo2's channel_ab.c/site.c/ monitor_c.c). Without this, glibc's strict-C99 mode hides these declarations entirely: this exact omission passed on macOS (Apple's libc does not gate them behind the same feature-test macro) but failed Linux CI with "storage size of 'sa' isn't
known" / implicit-declaration errors under -Werror - caught via a real GitHub Actions failure, not local testing. | |
| #define | SAPI_APPMANAGER_HAVE_POSIX_SIGNALS 0 |
| 1 when compiled on a POSIX-ish target (signal.h available) so sapi_appmanager_install_default_signal_handlers() can install a real SIGINT/SIGTERM handler; 0 otherwise, in which case that function returns SAPI_STATUS_NOT_SUPPORTED. | |
Functions | |
| static bool | sapi_appmanager_handle_stage_result (sapi_status_t status, const char *stage_name, uint32_t error_threshold) |
| Records the outcome of one per-cycle stage (checkpoint, pre_execute, execute, or post_execute) against the shared error accounting, and decides whether the remaining stages of this cycle should run. | |
| static void | sapi_appmanager_checkpoint_signature_reset (void) |
| Resets g_checkpoint_signature to a fixed seed and marks it active for the current cycle - called once per sapi_appmanager_run() loop iteration, before pre_execute() (ADR-034). | |
| static void | sapi_appmanager_encode_u64_le (uint8_t out[8], uint64_t value) |
| Packs a uint64_t into an 8-byte buffer, explicit little-endian - same convention sapi_checkpoint.c's own build_arrival_message() already uses, so a fold computed on one CPU architecture and compared against a peer's own fold on a different architecture still agrees (no raw struct/memcpy of a multi-byte integer across a network). | |
| uint32_t | sapi_appmanager_checkpoint_fold_signature (uint64_t signature) |
| Pure helper: folds a 64-bit checkpoint signature down to the uint32_t sapi_checkpoint_config_t::checkpoint_id expects (ADR-034). | |
| void | sapi_appmanager_checkpoint_mark (const char *file, int32_t line, const char *label) |
| Folds a hash of this call site into the current cycle's checkpoint signature (ADR-034). | |
| int | sapi_appmanager_run (const sapi_appmanager_config_t *config) |
| Run application with lifecycle management. | |
| sapi_app_state_t | sapi_appmanager_get_state (void) |
| Get current application state. | |
| sapi_status_t | sapi_appmanager_get_stats (sapi_appmanager_state_t *state) |
| Get application statistics. | |
| void | sapi_appmanager_request_shutdown (void) |
| Request application shutdown. | |
| void | sapi_appmanager_reset_state (void) |
| Forcibly resets the application manager's own bookkeeping (lifecycle state, iteration/error counters, shutdown-request flag, and the ADR-026 setup-phase lock) back to its initial, pre-run condition. | |
| sapi_status_t | sapi_appmanager_install_default_signal_handlers (void) |
| POSIX-only convenience: installs SIGINT and SIGTERM handlers that call sapi_appmanager_request_shutdown(), so an operator (Ctrl+C) or process manager (SIGTERM) can stop a sapi_appmanager_run() loop gracefully - shutdown() still runs, this is not a hard kill. | |
Variables | |
| static sapi_appmanager_state_t | g_app_state |
| Global application state (single instance; no dynamic allocation). | |
| static volatile int | g_shutdown_requested = 0 |
| Set by the installed signal handler (or sapi_appmanager_request_shutdown()) to request that sapi_appmanager_run()'s loop exit cleanly. | |
| static uint64_t | g_checkpoint_signature |
| Running per-cycle checkpoint-mark signature (ADR-034) - see sapi_appmanager_checkpoint_mark()'s own doc in the header. Reset once per cycle by sapi_appmanager_checkpoint_signature_reset(); folded by every sapi_appmanager_checkpoint_mark() call in between. Deliberately NOT part of the public sapi_appmanager_state_t (no consumer needs to read it directly - only the folded checkpoint_id, computed on demand by sapi_appmanager_checkpoint_fold_signature(), leaves this file). | |
| static bool | g_checkpoint_signature_active |
| True once g_checkpoint_signature has been reset for the CURRENT sapi_appmanager_run() cycle - see sapi_appmanager_checkpoint_mark()'s doc: a mark call outside an active cycle (before the loop starts, or after it ends) is a documented no-op rather than silently folding into whatever a NEXT, unrelated run's first cycle computes. | |
Application Manager implementation.
Provides lifecycle management for safety-critical applications.
Definition in file sapi_appmanager.c.
| #define _POSIX_C_SOURCE 200809L |
struct sigaction/sigaction()/sigemptyset() below are POSIX.1-2001, not base ISO C99 - must be defined before ANY header is included (same rule/pattern as safeAPIRBC2oo2's channel_ab.c/site.c/ monitor_c.c). Without this, glibc's strict-C99 mode hides these declarations entirely: this exact omission passed on macOS (Apple's libc does not gate them behind the same feature-test macro) but failed Linux CI with "storage size of 'sa' isn't known" / implicit-declaration errors under -Werror - caught via a real GitHub Actions failure, not local testing.
Definition at line 13 of file sapi_appmanager.c.
| #define SAPI_APPMANAGER_HAVE_POSIX_SIGNALS 0 |
1 when compiled on a POSIX-ish target (signal.h available) so sapi_appmanager_install_default_signal_handlers() can install a real SIGINT/SIGTERM handler; 0 otherwise, in which case that function returns SAPI_STATUS_NOT_SUPPORTED.
Definition at line 50 of file sapi_appmanager.c.
|
static |
Records the outcome of one per-cycle stage (checkpoint, pre_execute, execute, or post_execute) against the shared error accounting, and decides whether the remaining stages of this cycle should run.
Centralizes the "log, count against error_count, check error_threshold" behavior that ADR-019's checkpoint/pre_execute/post_execute stages share with execute()'s pre-existing error handling, so all four stages react to a non-OK status identically (REQ-APPMANAGER-007).
| status | Status returned by the stage that just ran. |
| stage_name | Short, human-readable stage name for the log line on failure (e.g. "checkpoint", "pre_execute"). Must not be NULL. |
| error_threshold | Errors before shutdown (0 = no limit), forwarded from sapi_appmanager_config_t::error_threshold. |
Definition at line 87 of file sapi_appmanager.c.
|
static |
Resets g_checkpoint_signature to a fixed seed and marks it active for the current cycle - called once per sapi_appmanager_run() loop iteration, before pre_execute() (ADR-034).
Definition at line 136 of file sapi_appmanager.c.
|
static |
Packs a uint64_t into an 8-byte buffer, explicit little-endian - same convention sapi_checkpoint.c's own build_arrival_message() already uses, so a fold computed on one CPU architecture and compared against a peer's own fold on a different architecture still agrees (no raw struct/memcpy of a multi-byte integer across a network).
Definition at line 150 of file sapi_appmanager.c.
|
static |
Global application state (single instance; no dynamic allocation).
Definition at line 54 of file sapi_appmanager.c.
|
static |
Set by the installed signal handler (or sapi_appmanager_request_shutdown()) to request that sapi_appmanager_run()'s loop exit cleanly.
Definition at line 63 of file sapi_appmanager.c.
|
static |
Running per-cycle checkpoint-mark signature (ADR-034) - see sapi_appmanager_checkpoint_mark()'s own doc in the header. Reset once per cycle by sapi_appmanager_checkpoint_signature_reset(); folded by every sapi_appmanager_checkpoint_mark() call in between. Deliberately NOT part of the public sapi_appmanager_state_t (no consumer needs to read it directly - only the folded checkpoint_id, computed on demand by sapi_appmanager_checkpoint_fold_signature(), leaves this file).
Definition at line 121 of file sapi_appmanager.c.
|
static |
True once g_checkpoint_signature has been reset for the CURRENT sapi_appmanager_run() cycle - see sapi_appmanager_checkpoint_mark()'s doc: a mark call outside an active cycle (before the loop starts, or after it ends) is a documented no-op rather than silently folding into whatever a NEXT, unrelated run's first cycle computes.
Definition at line 129 of file sapi_appmanager.c.