*
* @param[in] buffer to clear cursor of.
*/
-static inline void fr_strerror_clear(fr_log_buffer_t *buffer)
+static inline CC_HINT(always_inline) void fr_strerror_clear(fr_log_buffer_t *buffer, bool clear_pools)
{
+ if (clear_pools) {
+ talloc_free_children(buffer->pool_a);
+ talloc_free_children(buffer->pool_b);
+ }
fr_dlist_talloc_init(&buffer->entries, fr_log_entry_t, list);
}
fr_thread_local_set_destructor(fr_strerror_buffer, _fr_logging_free, buffer);
- fr_strerror_clear(buffer);
+ fr_strerror_clear(buffer, false);
}
return buffer;
}
-/**
+/*
+ * If last pool was pool_a, allocate from pool_b
+ * ...and vice versa. This prevents the pools
+ * from leaking due to non-contiguous allocations
+ * when we're using fr_strerror as an argument
+ * for another message.
+ */
+static inline CC_HINT(always_inline) TALLOC_CTX *pool_alternate(fr_log_buffer_t *buffer)
+{
+ if (buffer->pool == buffer->pool_a) {
+ buffer->pool = buffer->pool_b;
+ return buffer->pool;
+ }
+
+ return buffer->pool = buffer->pool_a;
+}
+
+static inline CC_HINT(always_inline) void pool_free_alt(fr_log_buffer_t *buffer)
+{
+ if (buffer->pool == buffer->pool_a) {
+ talloc_free_children(buffer->pool_b);
+ return;
+ }
+ talloc_free_children(buffer->pool_a);
+}
+
+/** Create an entry in the thread local logging stack, clearing all other entries
*
* @hidecallergraph
*/
-static fr_log_entry_t *fr_strerror_vprintf(char const *fmt, va_list ap)
+static fr_log_entry_t *strerror_vprintf(char const *fmt, va_list ap)
{
va_list ap_p;
fr_log_entry_t *entry;
* Clear any existing log messages
*/
if (!fmt) {
- talloc_free_children(buffer->pool);
- fr_strerror_clear(buffer);
-
+ fr_strerror_clear(buffer, true);
return NULL;
}
- /*
- * If last pool was pool_a, allocate from pool_b
- */
- if (buffer->pool == buffer->pool_a) {
- entry = talloc_zero(buffer->pool_b, fr_log_entry_t);
- if (!entry) {
- oom:
- fr_perror("Failed allocating memory for libradius error buffer");
- return NULL;
- }
-
- va_copy(ap_p, ap);
- entry->msg = fr_vasprintf(entry, fmt, ap_p);
- va_end(ap_p);
- if (!entry->msg) goto oom;
-
- talloc_free_children(buffer->pool);
- buffer->pool = buffer->pool_b;
- /*
- * ...and vice versa. This prevents the pools
- * from leaking due to non-contiguous allocations
- * when we're using fr_strerror as an argument
- * for another message.
- */
- } else {
- entry = talloc_zero(buffer->pool_a, fr_log_entry_t);
- if (!entry) goto oom;
-
- va_copy(ap_p, ap);
- entry->msg = fr_vasprintf(entry, fmt, ap_p);
- va_end(ap_p);
- if (!entry->msg) goto oom;
-
- talloc_free_children(buffer->pool);
- buffer->pool = buffer->pool_a;
+ entry = talloc_zero(pool_alternate(buffer), fr_log_entry_t);
+ if (!entry) {
+ oom:
+ fr_perror("Failed allocating memory for libradius error buffer");
+ return NULL;
}
- fr_strerror_clear(buffer);
+ va_copy(ap_p, ap);
+ entry->msg = fr_vasprintf(entry, fmt, ap_p);
+ va_end(ap_p);
+ if (!entry->msg) goto oom;
+
+ pool_free_alt(buffer);
+ fr_strerror_clear(buffer, false);
fr_dlist_insert_tail(&buffer->entries, entry);
return entry;
}
-/** Log to thread local error buffer
- *
- * @param[in] fmt printf style format string.
- * If NULL clears any existing messages.
- * @param[in] ... Arguments for the format string.
- *
- * @hidecallergraph
- */
-void fr_strerror_printf(char const *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- fr_strerror_vprintf(fmt, ap);
- va_end(ap);
-}
-
-/** Add an error marker to an existing stack of messages
- *
- * @param[in] subject to mark up.
- * @param[in] offset Positive offset to show where the error
- * should be positioned.
- * @param[in] fmt Error string.
- * @param[in] ... Arguments for the error string.
- *
- * @hidecallergraph
- */
-void fr_strerror_marker_printf(char const *subject, size_t offset, char const *fmt, ...)
-{
- va_list ap;
- fr_log_entry_t *entry;
-
- va_start(ap, fmt);
- entry = fr_strerror_vprintf(fmt, ap);
- va_end(ap);
-
- if (!entry) return;
-
- entry->subject = talloc_strdup(entry, subject);
- entry->offset = offset;
-}
-
/** Add a message to an existing stack of messages
*
* @param[in] fmt printf style format string.
*
* @hidecallergraph
*/
-static fr_log_entry_t *strerror_vprintf_push(char const *fmt, va_list ap)
+static fr_log_entry_t *strerror_vprintf_push(fr_log_buffer_t *buffer, char const *fmt, va_list ap)
{
va_list ap_p;
fr_log_entry_t *entry;
- fr_log_buffer_t *buffer;
if (!fmt) return NULL;
- buffer = fr_strerror_init();
- if (!buffer) return NULL;
-
/*
* Address pathological case where we could leak memory
* if only a combination of fr_strerror and
*/
if (!fr_dlist_num_elements(&buffer->entries)) talloc_free_children(buffer->pool);
- entry = talloc_zero(buffer->pool_b, fr_log_entry_t);
+ entry = talloc_zero(pool_alternate(buffer), fr_log_entry_t);
if (!entry) {
oom:
fr_perror("Failed allocating memory for libradius error buffer");
return entry;
}
-/** Add a message to an existing stack of messages
+/** Log to thread local error buffer
+ *
+ * @param[in] fmt printf style format string.
+ * If NULL clears any existing messages.
+ * @param[in] ... Arguments for the format string.
+ *
+ * @hidecallergraph
+ */
+void fr_strerror_printf(char const *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ strerror_vprintf(fmt, ap);
+ va_end(ap);
+}
+
+/** Add a message to an existing stack of messages at the tail
*
* @param[in] fmt printf style format string.
* If NULL clears any existing messages.
if (!buffer) return;
va_start(ap, fmt);
- entry = strerror_vprintf_push(fmt, ap);
+ entry = strerror_vprintf_push(buffer, fmt, ap);
va_end(ap);
if (!entry) return;
fr_dlist_insert_tail(&buffer->entries, entry);
}
-/** Add a message to an existing stack of messages
+/** Add a message to an existing stack of messages at the head
*
* @param[in] fmt printf style format string.
* If NULL clears any existing messages.
if (!buffer) return;
va_start(ap, fmt);
- entry = strerror_vprintf_push(fmt, ap);
+ entry = strerror_vprintf_push(buffer, fmt, ap);
va_end(ap);
if (!entry) return;
*
* @hidecallergraph
*/
+void fr_strerror_marker_printf(char const *subject, size_t offset, char const *fmt, ...)
+{
+ va_list ap;
+ fr_log_entry_t *entry;
+
+ va_start(ap, fmt);
+ entry = strerror_vprintf(fmt, ap);
+ va_end(ap);
+
+ if (!entry) return;
+
+ entry->subject = talloc_strdup(entry, subject);
+ entry->offset = offset;
+}
+
+/** Add an error marker to an existing stack of messages at the tail
+ *
+ * @param[in] subject to mark up.
+ * @param[in] offset Positive offset to show where the error
+ * should be positioned.
+ * @param[in] fmt Error string.
+ * @param[in] ... Arguments for the error string.
+ *
+ * @hidecallergraph
+ */
void fr_strerror_marker_printf_push(char const *subject, size_t offset, char const *fmt, ...)
{
va_list ap;
if (!buffer) return;
va_start(ap, fmt);
- entry = strerror_vprintf_push(fmt, ap);
+ entry = strerror_vprintf_push(buffer, fmt, ap);
va_end(ap);
if (!entry) return;
fr_dlist_insert_tail(&buffer->entries, entry);
}
-
-/** Add an error marker to an existing stack of messages
+/** Add an error marker to an existing stack of messages at the head
*
* @param[in] subject to mark up.
* @param[in] offset Positive offset to show where the error
if (!buffer) return;
va_start(ap, fmt);
- entry = strerror_vprintf_push(fmt, ap);
+ entry = strerror_vprintf_push(buffer, fmt, ap);
va_end(ap);
if (!entry) return;
fr_dlist_insert_head(&buffer->entries, entry);
}
+/** Create an entry in the thread local logging stack using a const string, clearing all other entries
+ *
+ * @hidecallergraph
+ */
+static fr_log_entry_t *strerror_const(char const *msg)
+{
+ fr_log_entry_t *entry;
+ fr_log_buffer_t *buffer;
+
+ buffer = fr_strerror_init();
+ if (!buffer) return NULL;
+
+ /*
+ * Clear any existing log messages
+ */
+ if (!msg) {
+ fr_strerror_clear(buffer, true);
+ return NULL;
+ }
+
+ entry = talloc_zero(pool_alternate(buffer), fr_log_entry_t);
+ if (!entry) {
+ fr_perror("Failed allocating memory for libradius error buffer");
+ return NULL;
+ }
+ memcpy(&entry->msg, &msg, sizeof(entry->msg));
+
+ pool_free_alt(buffer);
+ fr_strerror_clear(buffer, false);
+ fr_dlist_insert_tail(&buffer->entries, entry);
+
+ return entry;
+}
+
+/** Log to thread local error buffer
+ *
+ * @param[in] msg To add to error stack. Must have a
+ * lifetime equal to that of the program.
+ * @hidecallergraph
+ */
+void fr_strerror_const(char const *msg)
+{
+ (void)strerror_const(msg);
+}
+
+/** Add a message to an existing stack of messages
+ *
+ * @param[in] msg To add to error stack. Must have a
+ * lifetime equal to that of the program.
+ *
+ * @hidecallergraph
+ */
+static fr_log_entry_t *strerror_const_push(fr_log_buffer_t *buffer, char const *msg)
+{
+ fr_log_entry_t *entry;
+
+ if (!msg) return NULL;
+
+ /*
+ * Address pathological case where we could leak memory
+ * if only a combination of fr_strerror and
+ * fr_strerror_printf_push are used.
+ */
+ if (!fr_dlist_num_elements(&buffer->entries)) talloc_free_children(buffer->pool);
+
+ entry = talloc_zero(pool_alternate(buffer), fr_log_entry_t);
+ if (!entry) {
+ fr_perror("Failed allocating memory for libradius error buffer");
+ return NULL;
+ }
+ memcpy(&entry->msg, &msg, sizeof(entry->msg));
+
+ return entry;
+}
+
+/** Add a message to an existing stack of messages at the tail
+ *
+ * @param[in] msg To add to error stack. Must have a
+ * lifetime equal to that of the program.
+ *
+ * @hidecallergraph
+ */
+void fr_strerror_const_push(char const *msg)
+{
+ fr_log_buffer_t *buffer;
+ fr_log_entry_t *entry;
+
+ buffer = fr_strerror_init();
+ if (!buffer) return;
+
+ entry = strerror_const_push(buffer, msg);
+
+ if (!entry) return;
+
+ fr_dlist_insert_tail(&buffer->entries, entry);
+}
+
+/** Add a message to an existing stack of messages at the head
+ *
+ * @param[in] msg To add to error stack. Must have a
+ * lifetime equal to that of the program.
+ *
+ * @hidecallergraph
+ */
+void fr_strerror_const_push_head(char const *msg)
+{
+ fr_log_buffer_t *buffer;
+ fr_log_entry_t *entry;
+
+ buffer = fr_strerror_init();
+ if (!buffer) return;
+
+ entry = strerror_const_push(buffer, msg);
+
+ if (!entry) return;
+
+ fr_dlist_insert_head(&buffer->entries, entry);
+}
+
/** Get the last library error
*
* Will only return the last library error once, after which it will return a zero length string.
* Memory gets freed on next call to
* fr_strerror_printf or fr_strerror_printf_push.
*/
- fr_strerror_clear(buffer);
+ fr_strerror_clear(buffer, false);
return entry->msg;
}
* Memory gets freed on next call to
* fr_strerror_printf or fr_strerror_printf_push.
*/
- fr_strerror_clear(buffer);
+ fr_strerror_clear(buffer, false);
*subject = entry->subject;
*offset = entry->offset;
#include "strerror.c"
-static void test_strerror_uninit(void)
+static void strerror_uninit(void)
{
char const *error;
TEST_CHECK(error && (error[0] == '\0'));
}
-static void test_strerror_pop_uninit(void)
+static void strerror_pop_uninit(void)
{
char const *error;
TEST_CHECK(error == NULL);
}
-static void test_strerror_printf(void)
+static void strerror_printf(void)
{
char const *error;
TEST_CHECK(error && (error[0] == '\0'));
}
-static void test_strerror_printf_push_pop(void)
+static void strerror_printf_push_pop(void)
{
char const *error;
TEST_CHECK(error && (error[0] == '\0'));
}
-static void test_strerror_printf_push_strerror(void)
+static void strerror_printf_push_strerror(void)
{
char const *error;
TEST_CHECK(error == NULL);
}
-static void test_strerror_printf_push_pop_multi(void)
+static void strerror_printf_push_pop_multi(void)
{
char const *error;
TEST_CHECK(error && (error[0] == '\0'));
}
-static void test_strerror_printf_push_strerror_multi(void)
+static void strerror_printf_push_strerror_multi(void)
{
char const *error;
TEST_CHECK(error == NULL);
}
-static void test_strerror_printf_strerror_append(void)
+static void strerror_printf_strerror_append(void)
{
char const *error;
TEST_CHECK(error && (error[0] == '\0'));
}
-static void test_strerror_printf_push_append(void)
+static void strerror_printf_push_append(void)
{
char const *error;
TEST_CHECK(error && (error[0] == '\0'));
}
-static void test_strerror_printf_push_append2(void)
+static void strerror_printf_push_append2(void)
{
char const *error;
}
TEST_LIST = {
- { "test_strerror_uninit", test_strerror_uninit },
- { "test_strerror_pop_uninit", test_strerror_pop_uninit },
-
- { "test_strerror_printf", test_strerror_printf },
- { "test_strerror_printf_push_pop", test_strerror_printf_push_pop },
-
- { "test_strerror_printf_push_strerror", test_strerror_printf_push_strerror },
- { "test_strerror_printf_push_pop_multi", test_strerror_printf_push_pop_multi },
- { "test_strerror_printf_push_strerror_multi", test_strerror_printf_push_strerror_multi },
- { "test_strerror_printf_strerror_append", test_strerror_printf_strerror_append },
- { "test_strerror_printf_push_append", test_strerror_printf_push_append },
- { "test_strerror_printf_push_append2", test_strerror_printf_push_append2 },
+ { "strerror_uninit", strerror_uninit },
+ { "strerror_pop_uninit", strerror_pop_uninit },
+
+ { "strerror_printf", strerror_printf },
+ { "strerror_printf_push_pop", strerror_printf_push_pop },
+
+ { "strerror_printf_push_strerror", strerror_printf_push_strerror },
+ { "strerror_printf_push_pop_multi", strerror_printf_push_pop_multi },
+ { "strerror_printf_push_strerror_multi",strerror_printf_push_strerror_multi },
+ { "strerror_printf_strerror_append", strerror_printf_strerror_append },
+ { "strerror_printf_push_append", strerror_printf_push_append },
+ { "strerror_printf_push_append2", strerror_printf_push_append2 },
{ 0 }
};