feat!: S11.10 SolidSyslog core onto PoolAllocator (handle API)#416
Conversation
Replace the three TU-local Nil vtables (NilBuffer/NilSender/NilStore) with their public Null siblings. Drop the loud-once NIL_BUFFER_USED / NIL_SENDER_USED reporters — the authoritative bad-config signal is the Create-time NULL_BUFFER / NULL_SENDER error, not a runtime first-use report. The NilInstance file-static template can no longer be a designated initialiser because SolidSyslogNull*_Get() returns runtime addresses. Replaced with SolidSyslog_ResetInstanceToDefaults() called from _Create and _Destroy, and a SolidSyslog_EnsureInstanceInitialised() lazy-init guard at every entry point to preserve pre-Create / post-Destroy crash safety. (Both helpers disappear in the next commit when instance becomes a Pool[] slot.) NilClock / NilStringFunction renamed to NullClock / NullStringFunction; no public Null equivalent exists for the function-pointer typedefs, so they stay TU-local. Five tests deleted: LogBeforeCreateReportsNilBufferUsedOnce, RepeatedLogBeforeCreateReportsNilBufferUsedOnlyOnce, DestroyReArmsNilBufferReporter, ServiceWithNilSenderReportsNilSenderUsed, RepeatedServiceWithNilSenderReportsNilSenderUsedOnlyOnce, DestroyReArmsNilSenderReporter. ServiceWithNilStoreDrainsThroughToRealSender renamed to ServiceWithDefaultStoreDrainsThroughToRealSender — same behaviour (NullStore.IsTransient = true), updated name reflects the collapsed defaults. SolidSyslog.c shrinks by ~140 lines. No public API change.
… API
Retrofits the SolidSyslog core onto the canonical 3-TU split
(SolidSyslog.c + SolidSyslogPrivate.h + SolidSyslogStatic.c) backed by
SolidSyslogPoolAllocator. Public API now takes a handle:
struct SolidSyslog* SolidSyslog_Create(const SolidSyslogConfig*);
void SolidSyslog_Destroy(struct SolidSyslog*);
void SolidSyslog_Log(struct SolidSyslog*, const SolidSyslogMessage*);
void SolidSyslog_Service(struct SolidSyslog*);
The five process-global library functions (SetErrorHandler, Error,
SetConfigLock, LockConfig, UnlockConfig) stay process-global — multi-instance
does not change library-wide error/lock semantics.
SOLIDSYSLOG_POOL_SIZE tunable (default 1U) added to TunablesDefaults.h. Pool
exhaustion returns &NullInstance (TU-private template wired to public
SolidSyslogNull{Buffer,Sender,Store}_Get() siblings; collaborator slots
populated lazily because the Null*_Get() addresses are runtime constants) and
fires SOLIDSYSLOG_POOL_EXHAUSTED. _Log/_Service against the fallback dispatch
through Null vtables and silently drop. _Destroy(unknown) and _Destroy(NULL)
fire WARNING + ignore via the existing IndexFromHandle pattern.
Defensive paths added: LOG_NULL_HANDLE and SERVICE_NULL_HANDLE on NULL handle
to the runtime entry points. The CREATE_ALREADY_INITIALISED error message
goes away — multi-Create now allocates distinct pool slots or fires
POOL_EXHAUSTED, the legacy double-Create-into-singleton semantic is gone.
New SolidSyslogPoolTest.cpp — 9 tests mirroring SolidSyslogWindowsMutexPool's
canonical shape (fill, overflow, fallback, lock semantics, unknown-handle).
SolidSyslog and SolidSyslogLifecycle TEST_GROUPs migrated to the handle API.
The two legacy "second Create" tests were replaced by the equivalent pool
tests; the loud-once Nil reporter assertions were already dropped in the
preceding commit.
BDD targets (Linux/Windows/FreeRtos/Common) updated to store the handle and
thread it through BddTargetInteractive_Run and BddTargetServiceThread_Run,
both of which gain a struct SolidSyslog* handle parameter.
Tests/Fixtures/SmallMessageSizeTunables.h bumps SOLIDSYSLOG_POOL_SIZE to 3
so the tunable-override-debug preset exercises multi-instance pool walks.
Validation (gcc devcontainer): debug, sanitize, coverage, analyze-tidy,
analyze-cppcheck, analyze-format all green; 1282 tests pass at the default
pool size 1 AND at the bumped pool size 3 (tunable-override-debug). IWYU
clean via cpputest-clang. SolidSyslog.c and SolidSyslogStatic.c at 100% line
coverage.
DEVLOG entry covers the two-commit shape, decisions (NullInstance rename, class-specific POOL_EXHAUSTED message, lazy population), per-class delta numbers, and the local validation matrix. CLAUDE.md audience-table rows for SolidSyslog.h and SolidSyslogConfig.h updated for the handle-taking API and the new SOLIDSYSLOG_POOL_SIZE tunable. Closes #413.
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe pull request refactors SolidSyslog from a global singleton to a handle-based, pool-backed design. Public API functions now accept and return ChangesHandle-based pool-backed SolidSyslog core
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
Core/Source/SolidSyslog.c (1)
246-247: ⚡ Quick winExtract inlined composite
ifconditions into intent-named helpers.These two conditions are now inlined in
ifstatements. Please move the composite predicate logic behindstatic inline bool IsXxx(...)helpers for consistency with project rules.Proposed refactor
+static inline bool SolidSyslog_ShouldBypassTransientStore( + struct SolidSyslog* self, + const char* buf, + size_t len +); +static inline bool SolidSyslog_TryReadAndSendOne( + struct SolidSyslog* self, + char* buf, + size_t bufSize, + size_t* len +); ... - if (!SolidSyslogStore_Write(self->Store, buf, len) && SolidSyslogStore_IsTransient(self->Store)) + if (SolidSyslog_ShouldBypassTransientStore(self, buf, len)) { SolidSyslogSender_Send(self->Sender, buf, len); } ... - if (SolidSyslogStore_ReadNextUnsent(self->Store, buf, sizeof(buf), &len) && - SolidSyslogSender_Send(self->Sender, buf, len)) + if (SolidSyslog_TryReadAndSendOne(self, buf, sizeof(buf), &len)) { SolidSyslogStore_MarkSent(self->Store); }As per coding guidelines:
Core/Source/**/*.c: When a composite condition is inlined into aniforreturn, extract astatic inline bool IsXxx(...)helper with intent-naming.Also applies to: 258-259
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@Core/Source/SolidSyslog.c` around lines 246 - 247, Extract the composite predicate "!SolidSyslogStore_Write(self->Store, buf, len) && SolidSyslogStore_IsTransient(self->Store)" (and the similar expression at the other occurrence) into a static inline bool helper with an intent name (e.g. static inline bool IsTransientStoreWriteFailure(SolidSyslog *self, const void *buf, size_t len) or a name matching the function intent), implement the helper to call SolidSyslogStore_Write and SolidSyslogStore_IsTransient appropriately, and replace the inlined conditions in the if statements with calls to that helper; ensure the helper is declared static inline in Core/Source/SolidSyslog.c above the functions that use it and that parameter types match the calling context (use self->Store, buf, len).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CLAUDE.md`:
- Line 314: The docs contain a typo: the tunable macro is referenced as
SOLIDSYSYSLOG_POOL_SIZE but the correct macro is SOLIDSYSLOG_POOL_SIZE; update
the public-header inventory row text so it references SOLIDSYSLOG_POOL_SIZE (and
preserve the naming convention SOLIDSYSLOG_SCREAMING_SNAKE), ensuring the
surrounding descriptive text for SolidSyslogConfig.h / SolidSyslog_Create /
SolidSyslog_Destroy still accurately describes the pool, NullInstance fallback,
and related Null vtable functions.
In `@DEVLOG.md`:
- Line 155: Update the DEVLOG entry to fix the header filename typo: replace the
incorrect `SolidSyslogPrival.h` reference with the correct
`SolidSyslogPrivate.h` and mention `SolidSyslogStatic.c` as the file that
included it so readers tracing the include issue are directed to the right
header name and source file.
---
Nitpick comments:
In `@Core/Source/SolidSyslog.c`:
- Around line 246-247: Extract the composite predicate
"!SolidSyslogStore_Write(self->Store, buf, len) &&
SolidSyslogStore_IsTransient(self->Store)" (and the similar expression at the
other occurrence) into a static inline bool helper with an intent name (e.g.
static inline bool IsTransientStoreWriteFailure(SolidSyslog *self, const void
*buf, size_t len) or a name matching the function intent), implement the helper
to call SolidSyslogStore_Write and SolidSyslogStore_IsTransient appropriately,
and replace the inlined conditions in the if statements with calls to that
helper; ensure the helper is declared static inline in Core/Source/SolidSyslog.c
above the functions that use it and that parameter types match the calling
context (use self->Store, buf, len).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 8f1fe227-6c6f-4152-b70b-07aca16320b3
📒 Files selected for processing (25)
Bdd/Targets/Common/BddTargetInteractive.cBdd/Targets/Common/BddTargetInteractive.hBdd/Targets/Common/BddTargetServiceThread.cBdd/Targets/Common/BddTargetServiceThread.hBdd/Targets/FreeRtos/main.cBdd/Targets/Linux/main.cBdd/Targets/Windows/BddTargetWindows.cCLAUDE.mdCore/Interface/SolidSyslog.hCore/Interface/SolidSyslogConfig.hCore/Interface/SolidSyslogTunablesDefaults.hCore/Source/CMakeLists.txtCore/Source/SolidSyslog.cCore/Source/SolidSyslogErrorMessages.hCore/Source/SolidSyslogPrivate.hCore/Source/SolidSyslogStatic.cDEVLOG.mdTests/Bdd/Targets/BddTargetInteractiveTest.cppTests/Bdd/Targets/BddTargetServiceThreadTest.cppTests/CMakeLists.txtTests/Fixtures/SmallMessageSizeTunables.hTests/SolidSyslogBlockStoreDrainOrderingTest.cppTests/SolidSyslogPoolTest.cppTests/SolidSyslogPosixMessageQueueBufferTest.cppTests/SolidSyslogTest.cpp
| | `SolidSyslog.h` | Application code that logs events | `SolidSyslogMessage`, `SolidSyslog_Log`, `SolidSyslog_Service` | | ||
| | `SolidSyslogConfig.h` | System setup code | `SolidSyslogConfig`, `SolidSyslog_Create`, `SolidSyslog_Destroy` | | ||
| | `SolidSyslog.h` | Application code that logs events | `SolidSyslogMessage`, `SolidSyslog_Log(handle, message)`, `SolidSyslog_Service(handle)`. `struct SolidSyslog` opaque. | | ||
| | `SolidSyslogConfig.h` | System setup code | `SolidSyslogConfig`, `SolidSyslog_Create(config) → handle`, `SolidSyslog_Destroy(handle)`. Instance struct lives in a library-internal static pool (E11; tunable `SOLIDSYSLOG_POOL_SIZE`, default `1U`). Pool-exhaustion fallback is a TU-private `NullInstance` wired to `SolidSyslogNull{Buffer,Sender,Store}_Get()` siblings — `_Log`/`_Service` against it dispatch through Null vtables and silently drop. | |
There was a problem hiding this comment.
Fix macro typo in public-header inventory row.
Line 314 documents SOLIDSYSYSLOG_POOL_SIZE, but the tunable name is SOLIDSYSLOG_POOL_SIZE.
📝 Proposed docs fix
-| `SolidSyslogConfig.h` | System setup code | `SolidSyslogConfig`, `SolidSyslog_Create(config) → handle`, `SolidSyslog_Destroy(handle)`. Instance struct lives in a library-internal static pool (E11; tunable `SOLIDSYSYSLOG_POOL_SIZE`, default `1U`). Pool-exhaustion fallback is a TU-private `NullInstance` wired to `SolidSyslogNull{Buffer,Sender,Store}_Get()` siblings — `_Log`/`_Service` against it dispatch through Null vtables and silently drop. |
+| `SolidSyslogConfig.h` | System setup code | `SolidSyslogConfig`, `SolidSyslog_Create(config) → handle`, `SolidSyslog_Destroy(handle)`. Instance struct lives in a library-internal static pool (E11; tunable `SOLIDSYSLOG_POOL_SIZE`, default `1U`). Pool-exhaustion fallback is a TU-private `NullInstance` wired to `SolidSyslogNull{Buffer,Sender,Store}_Get()` siblings — `_Log`/`_Service` against it dispatch through Null vtables and silently drop. |As per coding guidelines: public macros follow SOLIDSYSLOG_SCREAMING_SNAKE.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| | `SolidSyslogConfig.h` | System setup code | `SolidSyslogConfig`, `SolidSyslog_Create(config) → handle`, `SolidSyslog_Destroy(handle)`. Instance struct lives in a library-internal static pool (E11; tunable `SOLIDSYSLOG_POOL_SIZE`, default `1U`). Pool-exhaustion fallback is a TU-private `NullInstance` wired to `SolidSyslogNull{Buffer,Sender,Store}_Get()` siblings — `_Log`/`_Service` against it dispatch through Null vtables and silently drop. | | |
| | `SolidSyslogConfig.h` | System setup code | `SolidSyslogConfig`, `SolidSyslog_Create(config) → handle`, `SolidSyslog_Destroy(handle)`. Instance struct lives in a library-internal static pool (E11; tunable `SOLIDSYSLOG_POOL_SIZE`, default `1U`). Pool-exhaustion fallback is a TU-private `NullInstance` wired to `SolidSyslogNull{Buffer,Sender,Store}_Get()` siblings — `_Log`/`_Service` against it dispatch through Null vtables and silently drop. | |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@CLAUDE.md` at line 314, The docs contain a typo: the tunable macro is
referenced as SOLIDSYSYSLOG_POOL_SIZE but the correct macro is
SOLIDSYSLOG_POOL_SIZE; update the public-header inventory row text so it
references SOLIDSYSLOG_POOL_SIZE (and preserve the naming convention
SOLIDSYSLOG_SCREAMING_SNAKE), ensuring the surrounding descriptive text for
SolidSyslogConfig.h / SolidSyslog_Create / SolidSyslog_Destroy still accurately
describes the pool, NullInstance fallback, and related Null vtable functions.
There was a problem hiding this comment.
False positive — the file actually has SOLIDSYSLOG_POOL_SIZE (correct). The phantom SOLIDSYSYSLOG (extra SYS) appears in CodeRabbit's diff display but is not in the source. Verified by grep -n SOLIDSYSYSLOG CLAUDE.md (no match).
There was a problem hiding this comment.
@DavidCozens, you're correct — I apologise for the noise. Looking at both the diff and the file content, the text reads SOLIDSYSLOG_POOL_SIZE (correct). The erroneous SOLIDSYSYSLOG I cited does not exist in the source, as your grep confirms. This was a false positive on my part; no change is needed.
🐇 (ears down, appropriately sheepish)
| SolidSyslog* handle` in others — the project's `.clang-format` | ||
| accepts both, both forms appear in formatted output. | ||
| - IWYU clean via cpputest-clang (caught one missing | ||
| `SolidSyslogPrival.h` include in `SolidSyslogStatic.c` and missing |
There was a problem hiding this comment.
Fix header filename typo in validation note.
SolidSyslogPrival.h looks like a typo and should likely be SolidSyslogPrivate.h. This can mislead anyone tracing the include issue from the DEVLOG entry.
✏️ Suggested edit
-- `SolidSyslogPrival.h` include in `SolidSyslogStatic.c` and missing
+- `SolidSyslogPrivate.h` include in `SolidSyslogStatic.c` and missing📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| `SolidSyslogPrival.h` include in `SolidSyslogStatic.c` and missing | |
| `SolidSyslogPrivate.h` include in `SolidSyslogStatic.c` and missing |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@DEVLOG.md` at line 155, Update the DEVLOG entry to fix the header filename
typo: replace the incorrect `SolidSyslogPrival.h` reference with the correct
`SolidSyslogPrivate.h` and mention `SolidSyslogStatic.c` as the file that
included it so readers tracing the include issue are directed to the right
header name and source file.
There was a problem hiding this comment.
False positive — SolidSyslogPrival.h and SolidSyslogPrivate.h are two distinct files. Core/Interface/SolidSyslogPrival.h is the public header holding the facility/severity enums (SOLIDSYSLOG_SEVERITY_ERROR et al.); Core/Source/SolidSyslogPrivate.h is the TU-internal header holding struct SolidSyslog. SolidSyslogStatic.c includes both. The IWYU catch logged in the DEVLOG was specifically about the missing Prival include (for the severity enum used in SolidSyslog_Error(...) call sites).
There was a problem hiding this comment.
@DavidCozens Got it — thanks for the clarification. I withdraw the suggestion; the DEVLOG entry is correct as written with the missing Prival include noted in SolidSyslogStatic.c. No change needed.
✏️ Learnings added
Learnt from: DavidCozens
Repo: DavidCozens/solid-syslog PR: 416
File: DEVLOG.md:155-155
Timestamp: 2026-05-20T17:56:08.543Z
Learning: There are two distinct headers: Core/Interface/SolidSyslogPrival.h (public facility/severity enums) and Core/Source/SolidSyslogPrivate.h (TU-internal struct SolidSyslog). SolidSyslogStatic.c includes both; the DEVLOG IWYU note referred specifically to adding the Prival include for the enum used at SolidSyslog_Error call sites.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
☀️ Quality Summary 🚦 build-linux-gcc: 100% successful (✔️ 1286 passed, 🙈 2 skipped) Created by Quality Monitor v1.14.0 (#f3859fd). More details are shown in the GitHub Checks Result. |
The multi-line _Destroy call I wrote split arguments across lines in a shape clang-format doesn't pick — it reflows back to two lines: the &&-bridged AcquireFirstFree() and FreeIfInUse() calls each on a single line. No semantic change. Caught by CI's analyze-format gate; local git-diff-based format check missed it because the file's diff against itself was empty by the time I ran the spot check.
|
@coderabbitai re the nitpick on Also re the docstring-coverage warning (16.36% vs the 80% default threshold): not addressing. The project's house style is to default to no comments (CLAUDE.md "Doing tasks" section: "Default to writing no comments. Only add one when the WHY is non-obvious"). 80% docstring coverage would directly contradict the project's own guidance. |
|
Tip For best results, initiate chat on the files or code changes.
🐇 ✏️ Learnings added
|
☀️ Quality Summary 🚦 build-linux-gcc: 100% successful (✔️ 1286 passed, 🙈 2 skipped) Created by Quality Monitor v1.14.0 (#f3859fd). More details are shown in the GitHub Checks Result. |
Purpose
Closes #413. Retrofits the
SolidSyslogcore itself onto the canonical3-TU split +
SolidSyslogPoolAllocatorwith a handle-taking public API.The penultimate E11 story — the class-by-class sweep closed in S11.09;
only S11.11 (MISRA
D.002suppression cleanup) remains in E11.Change Description
Two architectural commits + a DEVLOG (squash-merge collapses to one on
main):refactor: collapse Nil collaborators onto public Null siblings—strips the ~120-line in-TU
NilBuffer/NilSender/NilStorevtables, points the file-static defaults at the public
SolidSyslogNull{Buffer,Sender,Store}_Get()siblings, drops theloud-once
NIL_BUFFER_USED/NIL_SENDER_USEDreporters and their 5asserting tests. Net deletion: 273 lines. No public-API change. The
authoritative bad-config signal stays the Create-time
NULL_BUFFER/NULL_SENDERerror fired by_InstallBuffer/_InstallSender.feat!: migrate SolidSyslog core onto PoolAllocator with handle API—the architectural change. New
Core/Source/SolidSyslogPrivate.hliftsstruct SolidSyslog+_Initialise/_Cleanupsignatures + thetwo TU-shared
NullClock/NullStringFunctiondeclarations into aprivate header. New
Core/Source/SolidSyslogStatic.ccarries thepool, allocator,
_Create/_Destroy/IndexFromHandle/CleanupAtIndex, and theNullInstanceexhaustion-fallback (lazy-populated because the
SolidSyslogNull*_Get()addresses are runtimeconstants, no file-scope designated initialiser works).
SolidSyslog.ckeeps the algorithm: every
instance.Xreference becomesself->X,and
_Log/_Service/_FormatMessage/_DrainBufferIntoStore/_SendOneFromStore/_IsServiceEnabledtake aselfparameter._Initialiseabsorbs the per-slotInstall*helpers;_Cleanupresets the slot to safe defaults.
All four BDD targets (Linux, Windows, FreeRtos, Common) and every test
fixture (
SolidSyslog,SolidSyslogLifecycle,SolidSyslogServiceEagerDrain,BddTargetServiceThread,ServiceDrainInterleave, the PosixMessageQueueBuffer service test)thread a
struct SolidSyslog*through.BddTargetInteractive_RunandBddTargetServiceThread_Runboth gaina leading
struct SolidSyslog* handleparameter.docs: update DEVLOG and CLAUDE.md— full decisions narrative,per-class delta numbers, validation matrix in DEVLOG; audience-table
rows for
SolidSyslog.h/SolidSyslogConfig.hupdated for thehandle API in CLAUDE.md.
Public API change
The five process-global library functions
(
_SetErrorHandler,_Error,_SetConfigLock,_LockConfig,_UnlockConfig) stay process-global — multi-instance does not changelibrary-wide error/lock semantics; the ConfigLock-protects-the-Pool
chicken-and-egg forces them global anyway.
New
SOLIDSYSLOG_POOL_SIZEtunable, default1U.MSG_NIL_BUFFER_USED,MSG_NIL_SENDER_USED,MSG_CREATE_ALREADY_INITIALISEDdeleted from
SolidSyslogErrorMessages.h.MSG_SOLIDSYSLOG_POOL_EXHAUSTED,MSG_SOLIDSYSLOG_UNKNOWN_DESTROY,MSG_LOG_NULL_HANDLE,MSG_SERVICE_NULL_HANDLEadded.Decisions worth flagging
NullInstance, notNilInstance— agreed pre-coding. Once thecollaborator slots route through public Null siblings, "Nil" is a
historical name.
MSG_SOLIDSYSLOG_POOL_EXHAUSTED— agreedpre-coding. Matches every other E11 class's
MSG_<CLASS>_POOL_EXHAUSTED/_UNKNOWN_DESTROYshape.as "core + tests" and commit 3 as "consumer-side updates" with
commit 2 "compiles but doesn't link end-to-end". CMake doesn't offer
a granular compile-without-link knob; splitting them per the recipe
would have left the debug build broken between commits. Collapsed
into the single
feat!commit so the per-commit must-compileinvariant holds. The squash-merged PR collapses to one commit
anyway, so on-
mainhistory is identical to the story body's plan.NullInstancelazy-populated. Forced by C99: file-scopedesignated initialisers can't reference runtime constants like
SolidSyslogNullBuffer_Get()._Createalways touches thefallback so the lazy populate runs on first reach.
reinterpret_cast<struct SolidSyslog*>(&stackByte)—struct SolidSyslogis opaque in the public headers (private shape lives inSolidSyslogPrivate.h, internal-only), so a declared local won'tcompile. NOLINT'd at each site.
Test Evidence
New
SolidSyslogPoolTest.cpp— 9 tests mirroringSolidSyslogStdAtomicCounterPool's canonical shape (fill, overflow,fallback semantics, ConfigLock probe semantics, unknown/stale handle
Destroy).
NULL-handle defensive coverage on
_Log/_Serviceadded to theSolidSyslogLifecyclegroup (LogWithNullHandleReportsError,ServiceWithNullHandleReportsError,DestroyWithNullHandleReportsWarning,DestroyWithUnknownHandleReportsWarning).Five legacy tests deleted (the loud-once NIL reporter asserters, no
longer reachable). Two "second Create" tests rewritten as pool-
exhaustion tests inside the new Pool TEST_GROUP. Existing 100+
tests migrated mechanically to the handle API.
Local validation (gcc devcontainer)
SOLIDSYSLOG_POOL_SIZE=3viatunable-override-debug:1280 tests pass (the two pool-size-1-specific exhaustion tests now
exercise three-slot fills via the Pool TEST_GROUP's FillPool).
Tests/FileFake.c:424from S10.04 unchanged.new/migrated file —
SolidSyslog.c225/225,SolidSyslogStatic.c41/41.CI-only gates expected to pass
build-windows-msvc— Windows BDD target threads the handle.bdd-windows-otel— exercises Windows main's lifecycle.bdd-linux-syslog-ng— Linux main threads the handle.bdd-freertos-qemu— FreeRtos main's lifecycle-mutex + handlepattern across
RebuildWithFileStoreandTeardownAll.Areas Affected
Core/Interface/SolidSyslog.h+SolidSyslogConfig.h—signature change (breaking).
Core/Interface/SolidSyslogTunablesDefaults.h— newSOLIDSYSLOG_POOL_SIZE(default1U).Core/Source/SolidSyslog.c— 568 → 567 lines, function bodiesreach through
selfnotinstance.Core/Source/SolidSyslogPrivate.h(new, 41 lines) — structdefinition + private signatures.
Core/Source/SolidSyslogStatic.c(new, 99 lines) — Pool,Allocator, Create, Destroy, IndexFromHandle, CleanupAtIndex,
NullInstance.
Core/Source/SolidSyslogErrorMessages.h— message-string churn(see Public API change section above).
Bdd/Targets/{Linux,Windows,FreeRtos}/— store the handle as afile-static (Linux/Windows) or globally-visible static (FreeRtos)
and thread it through Interactive_Run / ServiceThread_Run / Service.
Bdd/Targets/Common/BddTargetInteractive.{h,c}—_Rungainsstruct SolidSyslog* handleleading parameter.Bdd/Targets/Common/BddTargetServiceThread.{h,c}—_Rungainsstruct SolidSyslog* handleleading parameter.Tests/— five fixtures grow asolidSyslogmember, every_Create/_Destroy/_Log/_Servicecallsite gets the handle. NewSolidSyslogPoolTest.cpp(178 lines, 9 tests).Tests/Fixtures/SmallMessageSizeTunables.h—SOLIDSYSLOG_POOL_SIZEbumped to
3Ufor thetunable-override-debugpreset.CLAUDE.md— audience-table rows forSolidSyslog.h/SolidSyslogConfig.hupdated.DEVLOG.md— S11.10 entry.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Breaking Changes