diff --git a/include/rcutils/logging.h b/include/rcutils/logging.h
index 42eb2406..f0e5e342 100644
--- a/include/rcutils/logging.h
+++ b/include/rcutils/logging.h
@@ -46,8 +46,30 @@ extern "C"
RCUTILS_PUBLIC
extern bool g_rcutils_logging_initialized;
+/// Initialize the logging allocator.
+/**
+ * This function is called automatically when using the logging macros.
+ * Initialize the logging allocator only if it is not initialized yet.
+ *
+ *
+ * Attribute | Adherence
+ * ------------------ | -------------
+ * Allocates Memory | No
+ * Thread-Safe | No
+ * Uses Atomics | No
+ * Lock-Free | Yes
+ *
+ * \return #RCUTILS_RET_OK if successful initialized, or
+ * \return #RCUTILS_RET_INVALID_ARGUMENT if the allocator is invalid.
+ */
+RCUTILS_PUBLIC
+RCUTILS_WARN_UNUSED
+rcutils_ret_t rcutils_logging_allocator_initialize(
+ const rcutils_allocator_t * allocator);
+
/// Initialize the logging system using the specified allocator.
/**
+ * Call rcutils_logging_allocator_initialize() using allocator argument.
* Initialize the logging system only if it was not in an initialized state.
*
* If an invalid allocator is passed, the initialization will fail.
diff --git a/src/logging.c b/src/logging.c
index 186ba24c..f3485ff6 100644
--- a/src/logging.c
+++ b/src/logging.c
@@ -510,17 +510,29 @@ static void parse_and_create_handlers_list(void)
}
}
+rcutils_ret_t rcutils_logging_allocator_initialize(
+ const rcutils_allocator_t * allocator)
+{
+ RCUTILS_CHECK_ALLOCATOR_WITH_MSG(
+ allocator, "invalid allocator", return RCUTILS_RET_INVALID_ARGUMENT);
+
+ if (rcutils_allocator_is_valid(&g_rcutils_logging_allocator)) {
+ return RCUTILS_RET_OK;
+ }
+ g_rcutils_logging_allocator = *allocator;
+
+ return RCUTILS_RET_OK;
+}
+
rcutils_ret_t rcutils_logging_initialize_with_allocator(rcutils_allocator_t allocator)
{
if (g_rcutils_logging_initialized) {
return RCUTILS_RET_OK;
}
- if (!rcutils_allocator_is_valid(&allocator)) {
- RCUTILS_SET_ERROR_MSG("Provided allocator is invalid.");
+ if (rcutils_logging_allocator_initialize(&allocator) != RCUTILS_RET_OK) {
return RCUTILS_RET_INVALID_ARGUMENT;
}
- g_rcutils_logging_allocator = allocator;
g_rcutils_logging_output_handler = &rcutils_logging_console_output_handler;
g_rcutils_logging_default_logger_level = RCUTILS_DEFAULT_LOGGER_DEFAULT_LEVEL;
@@ -691,6 +703,7 @@ rcutils_ret_t rcutils_logging_shutdown(void)
g_rcutils_logging_severities_map_valid = false;
}
g_num_log_msg_handlers = 0;
+ g_rcutils_logging_allocator = rcutils_get_zero_initialized_allocator();
g_rcutils_logging_initialized = false;
return ret;
}
diff --git a/test/test_logging.cpp b/test/test_logging.cpp
index 17463ae4..0454fd33 100644
--- a/test/test_logging.cpp
+++ b/test/test_logging.cpp
@@ -24,6 +24,18 @@
#include "rcutils/logging.h"
#include "rcutils/strdup.h"
+TEST(TestLogging, test_logging_allocator_initialization) {
+ rcutils_allocator_t allocator = rcutils_get_default_allocator();
+ rcutils_allocator_t invalid_allocator = rcutils_get_zero_initialized_allocator();
+
+ ASSERT_EQ(RCUTILS_RET_INVALID_ARGUMENT, rcutils_logging_allocator_initialize(NULL));
+ ASSERT_EQ(RCUTILS_RET_INVALID_ARGUMENT, rcutils_logging_allocator_initialize(&invalid_allocator));
+
+ ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_allocator_initialize(&allocator));
+ // 2nd time will also succeed.
+ ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_allocator_initialize(&allocator));
+}
+
TEST(TestLogging, test_logging_initialization) {
EXPECT_FALSE(g_rcutils_logging_initialized);
ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_initialize());