From 6c563627ea9052aadb69a0628e3ab558b2c587e8 Mon Sep 17 00:00:00 2001 From: David Cozens Date: Tue, 19 May 2026 20:36:00 +0100 Subject: [PATCH 1/2] feat: BDD target stderr handler exits on ERROR severity ERROR-class severities (EMERGENCY/ALERT/CRITICAL/ERROR) write 'BDD-TARGET: FATAL: \n', flush stderr, and _Exit(3). WARNING stays as the existing print-only line. Turns silent NULL-fallback-on-pool-exhaustion into a loud, debuggable BDD failure ('BDD target died' vs. 'oracle received 0 of 1'). --- Bdd/Targets/Common/BddTargetStderrErrorHandler.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Bdd/Targets/Common/BddTargetStderrErrorHandler.c b/Bdd/Targets/Common/BddTargetStderrErrorHandler.c index 6d7a2697..90330802 100644 --- a/Bdd/Targets/Common/BddTargetStderrErrorHandler.c +++ b/Bdd/Targets/Common/BddTargetStderrErrorHandler.c @@ -1,6 +1,7 @@ #include "BddTargetStderrErrorHandler.h" #include +#include #include "SolidSyslogError.h" #include "SolidSyslogPrival.h" @@ -8,7 +9,16 @@ static void StderrErrorHandler(void* context, enum SolidSyslogSeverity severity, const char* message) { (void) context; - (void) fprintf(stderr, "[solidsyslog] severity=%d %s\n", (int) severity, message); + if (severity <= SOLIDSYSLOG_SEVERITY_ERROR) + { + (void) fprintf(stderr, "BDD-TARGET: FATAL: %s\n", message); + (void) fflush(stderr); + _Exit(3); + } + else + { + (void) fprintf(stderr, "[solidsyslog] severity=%d %s\n", (int) severity, message); + } } void BddTargetStderrErrorHandler_Install(void) From c637a5d0993c99c8df386c4cc4fce267e32e8805 Mon Sep 17 00:00:00 2001 From: David Cozens Date: Tue, 19 May 2026 20:36:03 +0100 Subject: [PATCH 2/2] docs: update DEVLOG for BDD target stderr handler fatal exit --- DEVLOG.md | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/DEVLOG.md b/DEVLOG.md index 7f9d4a4c..a11b3b60 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -1,5 +1,61 @@ # Dev Log +## 2026-05-19 — BDD target stderr handler: fatal exit on ERROR severity + +Follow-up from S11.05 part B post-merge. The PR's final CI run took 23m +instead of the usual 4–5m. Per-step timing showed both +`build-linux-tunable-override` and `build-freertos-target` spent 16+ minutes +in the "Initialize containers" step (image pull from ghcr.io) while other +jobs on the same run using the same image pulled in seconds — runner +cold-cache, not a project regression. + +The genuine concern surfaced by that diagnosis: pool exhaustion in a BDD +wiring scenario would currently fail silently. `_Create` returns the shared +null object, the BDD target keeps running on it, the oracle receives +nothing, the scenario times out — and the captured failure mode is "oracle +received 0 of 1" rather than "BDD target died on POOL_EXHAUSTED". Same +failure class as part A's STREAM_SENDER default-1 bust. + +This PR hardens `BddTargetStderrErrorHandler` so any severity at or below +`SOLIDSYSLOG_SEVERITY_ERROR` (EMERGENCY/ALERT/CRITICAL/ERROR) writes +`BDD-TARGET: FATAL: \n` to stderr, flushes, and `_Exit(3)`. +WARNING stays as the existing print-only line (UNKNOWN_DESTROY noise). + +### Decisions + +- **`_Exit` not `_exit`.** C99 ``, portable to POSIX/MSVC/ + FreeRTOS-Posix; POSIX-only `_exit` would break the Windows BDD target. + Same no-atexit / no-stdio-flush semantics for our purpose — we + `fflush(stderr)` ourselves first so the FATAL marker reaches the wire + before the process disappears. + +- **`severity <= SOLIDSYSLOG_SEVERITY_ERROR`** rather than `==`. Catches + EMERGENCY/ALERT/CRITICAL too. The library only emits ERROR and WARNING + in practice today, so the two forms are equivalent now, but `<=` is the + defensible semantics — any future EMERGENCY would still mean "BDD target + is hosed". + +- **No unit test for the handler.** The handler is six production lines; a + `_Exit` seam (function-pointer indirection + paired interceptor test) is + more abstraction than the change justifies. Validation is the local gate + sweep (debug / sanitize / clang-debug / tidy / cppcheck / coverage / iwyu / + clang-format — all green) plus future BDD scenarios that deliberately + starve a pool, which don't yet exist. + +### Deferred + +- A pool-starvation BDD scenario that actually fires the new fatal path. + Today's scenarios all use healthy wiring, so the new branch is exercised + only by static analysis, not at runtime. Worth raising once an E11 sweep + story touches BDD wiring. + +### Open questions + +- The CI slowdown root cause (ghcr.io cold-cache image pull) is left as + watch-and-see. If it recurs, ticket the mitigation (slimmer base image, + GHCR retention/replication tier, or a small image-pull warm-up job that + other jobs gate on). + ## 2026-05-19 — S11.05 part B: BlockStore composition onto PoolAllocator Closes S11.05. The composition migration that part A deferred — RecordStore