Skip to content
Merged
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
7 changes: 4 additions & 3 deletions Bdd/Targets/Common/BddTargetInteractive.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ static int ParseCount(const char* args)
return (count > 0) ? count : 1;
}

static void HandleSend(const char* args, const struct SolidSyslogMessage* message)
static void HandleSend(struct SolidSyslog* handle, const char* args, const struct SolidSyslogMessage* message)
{
int count = ParseCount(args);

for (int i = 0; i < count; i++)
{
SolidSyslog_Log(message);
SolidSyslog_Log(handle, message);
}

printf("Sent %d message%s\n", count, (count == 1) ? "" : "s");
Expand All @@ -95,6 +95,7 @@ static void HandleSet(const char* args, BddTargetInteractiveSetHandler onSet)
}

void BddTargetInteractive_Run(
struct SolidSyslog* handle,
const struct SolidSyslogMessage* message,
FILE* input,
BddTargetInteractiveSwitchHandler onSwitch,
Expand All @@ -121,7 +122,7 @@ void BddTargetInteractive_Run(
const char* args = NULL;
if (MatchCommand(line, "send", &args))
{
HandleSend(args, message);
HandleSend(handle, args, message);
}
else if (onSwitch != NULL && MatchCommand(line, "switch", &args))
{
Expand Down
2 changes: 2 additions & 0 deletions Bdd/Targets/Common/BddTargetInteractive.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "ExternC.h"

struct SolidSyslog;
struct SolidSyslogMessage;

EXTERN_C_BEGIN
Expand All @@ -14,6 +15,7 @@ EXTERN_C_BEGIN
typedef bool (*BddTargetInteractiveSetHandler)(const char* name, const char* value);

void BddTargetInteractive_Run(
struct SolidSyslog * handle,
const struct SolidSyslogMessage* message,
FILE* input,
BddTargetInteractiveSwitchHandler onSwitch,
Expand Down
4 changes: 2 additions & 2 deletions Bdd/Targets/Common/BddTargetServiceThread.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ enum

// cppcheck-suppress constParameter -- volatile bool written by another thread; const would be incorrect
// NOLINTNEXTLINE(readability-non-const-parameter) -- volatile bool written by another thread; const would be incorrect
void BddTargetServiceThread_Run(volatile bool* shutdown, SolidSyslogSleepFunction sleep)
void BddTargetServiceThread_Run(struct SolidSyslog* handle, volatile bool* shutdown, SolidSyslogSleepFunction sleep)
{
while (!(*shutdown))
{
SolidSyslog_Service();
SolidSyslog_Service(handle);
sleep(IDLE_YIELD_MILLISECONDS);
}
}
8 changes: 7 additions & 1 deletion Bdd/Targets/Common/BddTargetServiceThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@

EXTERN_C_BEGIN

void BddTargetServiceThread_Run(volatile bool* shutdown, SolidSyslogSleepFunction sleep);
struct SolidSyslog;

void BddTargetServiceThread_Run(
struct SolidSyslog * handle,
volatile bool* shutdown,
SolidSyslogSleepFunction sleep
);

EXTERN_C_END

Expand Down
15 changes: 9 additions & 6 deletions Bdd/Targets/FreeRtos/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ static uint8_t bufferRing[SOLIDSYSLOG_CIRCULAR_BUFFER_RING_BYTES(BDD_TARGET_BUFF
* for one Service() call per iteration; the rebuild path holds it across
* Destroy → BlockStore_Create → Create. */
static struct SolidSyslogMutex* lifecycleMutex = NULL;
static struct SolidSyslog* solidSyslog = NULL;
static volatile bool solidSyslogReady;
/* Signals Service to self-delete BEFORE Teardown destroys the lifecycle
* mutex. Without this, Service races against InteractiveTask: Teardown
Expand Down Expand Up @@ -572,7 +573,8 @@ static bool RebuildWithFileStore(void)
}

solidSyslogReady = false;
SolidSyslog_Destroy();
SolidSyslog_Destroy(solidSyslog);
solidSyslog = NULL;
DestroyCurrentStore();

/* Build a fresh FatFs-backed BlockStore. With the volume mounted above,
Expand Down Expand Up @@ -602,7 +604,7 @@ static bool RebuildWithFileStore(void)
* sort order in target_driver.py guarantees `set no-sd` comes before
* `set store file` so the value is final by the time we get here. */
solidSyslogConfig.SdCount = pendingNoSd ? 1U : (sizeof(sdList) / sizeof(sdList[0]));
SolidSyslog_Create(&solidSyslogConfig);
solidSyslog = SolidSyslog_Create(&solidSyslogConfig);
solidSyslogReady = true;
SolidSyslogMutex_Unlock(lifecycleMutex);
return true;
Expand Down Expand Up @@ -637,7 +639,8 @@ static void TeardownAll(void)
SolidSyslogMutex_Lock(lifecycleMutex);
solidSyslogTeardown = true;
solidSyslogReady = false;
SolidSyslog_Destroy();
SolidSyslog_Destroy(solidSyslog);
solidSyslog = NULL;
SolidSyslogOriginSd_Destroy(originSd);
SolidSyslogTimeQualitySd_Destroy(timeQualitySd);
SolidSyslogMetaSd_Destroy(metaSd);
Expand Down Expand Up @@ -866,10 +869,10 @@ static void InteractiveTask(void* argument)
.SdCount = pendingNoSd ? 1U : (sizeof(sdList) / sizeof(sdList[0])),
};
SolidSyslog_SetErrorHandler(ErrorHandler, NULL);
SolidSyslog_Create(&solidSyslogConfig);
solidSyslog = SolidSyslog_Create(&solidSyslogConfig);
solidSyslogReady = true;

BddTargetInteractive_Run(&testMessage, stdin, BddTargetSwitchConfig_SetByName, OnSet);
BddTargetInteractive_Run(solidSyslog, &testMessage, stdin, BddTargetSwitchConfig_SetByName, OnSet);

/* Peak stack usage report on `quit`. Captured into every BDD run's QEMU
* console output so stack regressions surface in bdd-freertos-qemu logs
Expand Down Expand Up @@ -924,7 +927,7 @@ static void ServiceTask(void* argument)
}
if (solidSyslogReady)
{
SolidSyslog_Service();
SolidSyslog_Service(solidSyslog);
}
SolidSyslogMutex_Unlock(lifecycleMutex);
vTaskDelay(pdMS_TO_TICKS(1));
Expand Down
9 changes: 5 additions & 4 deletions Bdd/Targets/Linux/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ static void GetTimeQuality(struct SolidSyslogTimeQuality* timeQuality)
}

static volatile bool shutdown_flag;
static struct SolidSyslog* solidSyslog;

static void* ServiceThreadEntry(void* arg)
{
volatile bool* shutdown = (volatile bool*) arg;
BddTargetServiceThread_Run(shutdown, SolidSyslogPosixSleep);
BddTargetServiceThread_Run(solidSyslog, shutdown, SolidSyslogPosixSleep);
return NULL;
}

Expand Down Expand Up @@ -264,7 +265,7 @@ int main(int argc, char* argv[])
.Sd = sdList,
.SdCount = sdCount,
};
SolidSyslog_Create(&config);
solidSyslog = SolidSyslog_Create(&config);

shutdown_flag = false;
haltExit = options.HaltExit;
Expand All @@ -279,12 +280,12 @@ int main(int argc, char* argv[])
.Msg = options.Msg,
};

BddTargetInteractive_Run(&message, stdin, BddTargetSwitchConfig_SetByName, NULL);
BddTargetInteractive_Run(solidSyslog, &message, stdin, BddTargetSwitchConfig_SetByName, NULL);

shutdown_flag = true;
pthread_join(serviceThread, NULL);

SolidSyslog_Destroy();
SolidSyslog_Destroy(solidSyslog);
SolidSyslogOriginSd_Destroy(originSd);
SolidSyslogTimeQualitySd_Destroy(timeQuality);
SolidSyslogMetaSd_Destroy(metaSd);
Expand Down
9 changes: 5 additions & 4 deletions Bdd/Targets/Windows/BddTargetWindows.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ static const char* const THRESHOLD_MARKER_PATH = "Bdd/output/solidsyslog_thresho

static uint8_t bufferRing[SOLIDSYSLOG_CIRCULAR_BUFFER_RING_BYTES(BDD_TARGET_BUFFER_MESSAGES)];
static volatile bool shutdownFlag;
static struct SolidSyslog* solidSyslog;

/* Created in CreateSender, destroyed in DestroySender — held in file scope so
teardown can reach them after the SwitchingSender wraps them all. */
Expand All @@ -83,7 +84,7 @@ static struct SolidSyslogBlockDevice* storeBlockDevice;
// NOLINTNEXTLINE(readability-non-const-parameter) -- _beginthreadex thread-entry signature requires void*
static unsigned __stdcall ServiceThreadEntry(void* arg)
{
BddTargetServiceThread_Run((volatile bool*) arg, SolidSyslogWindowsSleep);
BddTargetServiceThread_Run(solidSyslog, (volatile bool*) arg, SolidSyslogWindowsSleep);
return 0;
}

Expand Down Expand Up @@ -333,7 +334,7 @@ int BddTargetWindows_Run(int argc, char* argv[])
.Sd = sdList,
.SdCount = sdCount,
};
SolidSyslog_Create(&config);
solidSyslog = SolidSyslog_Create(&config);

shutdownFlag = false;
HANDLE serviceThread = (HANDLE) _beginthreadex(NULL, 0, ServiceThreadEntry, (void*) &shutdownFlag, 0, NULL);
Expand All @@ -345,13 +346,13 @@ int BddTargetWindows_Run(int argc, char* argv[])
.Msg = options.Msg,
};

BddTargetInteractive_Run(&message, stdin, BddTargetSwitchConfig_SetByName, NULL);
BddTargetInteractive_Run(solidSyslog, &message, stdin, BddTargetSwitchConfig_SetByName, NULL);

shutdownFlag = true;
WaitForSingleObject(serviceThread, INFINITE);
CloseHandle(serviceThread);

SolidSyslog_Destroy();
SolidSyslog_Destroy(solidSyslog);
SolidSyslogOriginSd_Destroy(originSd);
SolidSyslogTimeQualitySd_Destroy(timeQuality);
SolidSyslogMetaSd_Destroy(metaSd);
Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,8 @@ live under `Core/Interface/`; platform-specific helpers (the `SolidSyslogPosix*`

| Header | Audience | Provides |
|---|---|---|
| `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. |

@coderabbitai coderabbitai Bot May 20, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

Suggested change
| `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.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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)

| `SolidSyslogError.h` | Any code installing a handler to react to library-internal errors (NULL guards, send failures); also the library-internal call site for emitting them | `SolidSyslogErrorHandler` typedef, `SolidSyslog_SetErrorHandler(handler, context)`, `SolidSyslog_Error(severity, message)`. Default handler is a silent no-op; setting `handler = NULL` restores the default. Single global slot — intended for setup-time configuration, not synchronised with concurrent `Error` calls. |
| `SolidSyslogConfigLock.h` | Setup code on systems where library-internal config-time critical sections (E11 pool `_Create`/`_Destroy` slot walks) may race across tasks or cores. Single-task setup needs nothing — defaults are no-ops. | `SolidSyslogConfigLockFunction` typedef (zero-arg `void(void)`), `SolidSyslog_SetConfigLock(lockFn, unlockFn)`, `SolidSyslog_LockConfig()`, `SolidSyslog_UnlockConfig()`. Pair API: both handlers installed together. `NULL` on either side restores that side's no-op default. Single global slot — intended for setup-time configuration, not synchronised with concurrent installs. Integrators wire `taskENTER_CRITICAL`/`taskEXIT_CRITICAL` (FreeRTOS), `pthread_mutex_lock`/`unlock` on a static `pthread_mutex_t` (POSIX), `EnterCriticalSection`/`LeaveCriticalSection` on a static `CRITICAL_SECTION` (Windows), or a spinlock pair. This is the only synchronisation primitive available to the Mutex and AtomicCounter pools for their own pool walks — chicken-and-egg eliminates their own injectables. |
| `SolidSyslogStringFunction.h` | Any code needing the string-callback typedef | `SolidSyslogStringFunction` (callback writes into a `SolidSyslogFormatter*`) — used by `SolidSyslogConfig` (hostname/appName/processId), `SolidSyslogMetaSdConfig` (language), `SolidSyslogOriginSdConfig` |
Expand Down
6 changes: 4 additions & 2 deletions Core/Interface/SolidSyslog.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

EXTERN_C_BEGIN

struct SolidSyslog;

struct SolidSyslogMessage
{
enum SolidSyslogFacility Facility;
Expand All @@ -14,8 +16,8 @@ EXTERN_C_BEGIN
const char* Msg;
};

void SolidSyslog_Log(const struct SolidSyslogMessage* message);
void SolidSyslog_Service(void);
void SolidSyslog_Log(struct SolidSyslog * handle, const struct SolidSyslogMessage* message);
void SolidSyslog_Service(struct SolidSyslog * handle);

EXTERN_C_END

Expand Down
5 changes: 3 additions & 2 deletions Core/Interface/SolidSyslogConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

EXTERN_C_BEGIN

struct SolidSyslog;
struct SolidSyslogBuffer;
struct SolidSyslogFormatter;
struct SolidSyslogSender;
Expand All @@ -28,8 +29,8 @@ EXTERN_C_BEGIN
size_t SdCount;
};

void SolidSyslog_Create(const struct SolidSyslogConfig* config);
void SolidSyslog_Destroy(void);
struct SolidSyslog* SolidSyslog_Create(const struct SolidSyslogConfig* config);
void SolidSyslog_Destroy(struct SolidSyslog * handle);

EXTERN_C_END

Expand Down
20 changes: 20 additions & 0 deletions Core/Interface/SolidSyslogTunablesDefaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,26 @@
#error "SOLIDSYSLOG_MAX_MESSAGE_SIZE must be >= 64"
#endif

/*
* Number of SolidSyslog instances the library's internal static pool
* can simultaneously hold. Each instance is a small bookkeeping struct
* (collaborator pointers + SD array pointer + count).
*
* Most integrators only ever create one SolidSyslog per process; default 1.
* Bump via SOLIDSYSLOG_USER_TUNABLES_FILE if the integrator needs multiple
* concurrent SolidSyslog instances.
*
* Floor: 1. Sub-floor values rejected at compile time.
*/
#ifndef SOLIDSYSLOG_POOL_SIZE
/* NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -- macro form required for preprocessor visibility (floor #if) and C array-size const-expr. */
#define SOLIDSYSLOG_POOL_SIZE 1U
#endif

#if SOLIDSYSLOG_POOL_SIZE < 1
#error "SOLIDSYSLOG_POOL_SIZE must be >= 1"
#endif

/*
* Number of SolidSyslogCircularBuffer instances the library's internal
* static pool can simultaneously hold. Each instance is a small
Expand Down
1 change: 1 addition & 0 deletions Core/Source/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
set(SOURCES
SolidSyslog.c
SolidSyslogStatic.c
SolidSyslogError.c
SolidSyslogConfigLock.c
SolidSyslogSwitchingSender.c
Expand Down
Loading
Loading