chiark / gitweb /
assert: store away assert msg before aborting, akin to glibc's __abort_msg
authorLennart Poettering <lennart@poettering.net>
Thu, 22 Apr 2010 01:51:26 +0000 (03:51 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 22 Apr 2010 01:51:26 +0000 (03:51 +0200)
log.c
log.h
macro.h

diff --git a/log.c b/log.c
index d8cc404..076fa00 100644 (file)
--- a/log.c
+++ b/log.c
@@ -40,6 +40,10 @@ static int log_max_level = LOG_DEBUG;
 static int syslog_fd = -1;
 static int kmsg_fd = -1;
 
+/* Akin to glibc's __abort_msg; which is private and we hance cannot
+ * use here. */
+static char *log_abort_msg = NULL;
+
 void log_close_kmsg(void) {
 
         if (kmsg_fd >= 0) {
@@ -245,6 +249,26 @@ static int write_to_kmsg(
         return 0;
 }
 
+#define LOG_DISPATCH(level,file,line,func,format)                       \
+        do {                                                            \
+                va_list _ap;                                            \
+                bool written = false;                                   \
+                if (log_target == LOG_TARGET_KMSG) {                    \
+                        va_start(_ap, format);                          \
+                        written = write_to_kmsg(level, file, line, func, format, _ap) >= 0; \
+                        va_end(_ap);                                    \
+                } else if (log_target == LOG_TARGET_SYSLOG) {           \
+                        va_start(_ap, format);                          \
+                        written = write_to_syslog(level, file, line, func, format, _ap) >= 0; \
+                        va_end(_ap);                                    \
+                }                                                       \
+                if (!written) {                                         \
+                        va_start(_ap, format);                          \
+                        write_to_console(level, file, line, func, format, _ap); \
+                        va_end(_ap);                                    \
+                }                                                       \
+        } while (false)
+
 void log_meta(
         int level,
         const char*file,
@@ -252,32 +276,37 @@ void log_meta(
         const char *func,
         const char *format, ...) {
 
-        va_list ap;
-        bool written;
         int saved_errno;
 
         if (LOG_PRI(level) > log_max_level)
                 return;
 
         saved_errno = errno;
-        written = false;
-
-        if (log_target == LOG_TARGET_KMSG) {
-                va_start(ap, format);
-                written = write_to_kmsg(level, file, line, func, format, ap) >= 0;
-                va_end(ap);
-        } else if (log_target == LOG_TARGET_SYSLOG) {
-                va_start(ap, format);
-                written = write_to_syslog(level, file, line, func, format, ap) >= 0;
-                va_end(ap);
-        }
+        LOG_DISPATCH(level, file, line, func, format);
+        errno = saved_errno;
+}
 
-        if (!written) {
-                va_start(ap, format);
-                write_to_console(level, file, line, func, format, ap);
-                va_end(ap);
-        }
+void log_assert(
+        const char*file,
+        int line,
+        const char *func,
+        const char *format, ...) {
+
+        static char buffer[LOG_BUFFER_MAX];
+        va_list ap;
+        int saved_errno = errno;
+
+        va_start(ap, format);
+        vsnprintf(buffer, sizeof(buffer), format, ap);
+        va_end(ap);
+
+        char_array_0(buffer);
+        log_abort_msg = buffer;
+
+        LOG_DISPATCH(LOG_CRIT, file, line, func, format);
+        abort();
 
+        /* If the user chose to ignore this SIGABRT, we are happy to go on, as if nothing happened. */
         errno = saved_errno;
 }
 
diff --git a/log.h b/log.h
index f424c19..0fc1834 100644 (file)
--- a/log.h
+++ b/log.h
@@ -57,6 +57,12 @@ void log_meta(
         const char *func,
         const char *format, ...) _printf_attr(5,6);
 
+_noreturn void log_assert(
+        const char*file,
+        int line,
+        const char *func,
+        const char *format, ...) _printf_attr(4,5);
+
 #define log_debug(...)   log_meta(LOG_DEBUG,   __FILE__, __LINE__, __func__, __VA_ARGS__)
 #define log_info(...)    log_meta(LOG_INFO,    __FILE__, __LINE__, __func__, __VA_ARGS__)
 #define log_notice(...)  log_meta(LOG_NOTICE,  __FILE__, __LINE__, __func__, __VA_ARGS__)
diff --git a/macro.h b/macro.h
index d56585d..2379ee2 100644 (file)
--- a/macro.h
+++ b/macro.h
@@ -35,6 +35,7 @@
 #define _deprecated __attribute__ ((deprecated))
 #define _packed __attribute__ ((packed))
 #define _malloc __attribute__ ((malloc))
+#define _weak __attribute__ ((weak))
 #define _likely(x) (__builtin_expect(!!(x),1))
 #define _unlikely(x) (__builtin_expect(!!(x),0))
 
@@ -69,11 +70,10 @@ static inline size_t ALIGN(size_t l) {
 
 #define assert_se(expr)                                                 \
         do {                                                            \
-                if (_unlikely(!(expr))) {                               \
-                        log_error("Assertion '%s' failed at %s:%u, function %s(). Aborting.", \
-                                  #expr , __FILE__, __LINE__, __PRETTY_FUNCTION__); \
-                        abort();                                        \
-                }                                                       \
+                if (_unlikely(!(expr)))                                 \
+                        log_assert(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
+                                   "Assertion '%s' failed at %s:%u, function %s(). Aborting.", \
+                                   #expr , __FILE__, __LINE__, __PRETTY_FUNCTION__); \
         } while (false)                                                 \
 
 /* We override the glibc assert() here. */
@@ -86,9 +86,9 @@ static inline size_t ALIGN(size_t l) {
 
 #define assert_not_reached(t)                                           \
         do {                                                            \
-                log_error("Code should not be reached '%s' at %s:%u, function %s(). Aborting.", \
-                          t, __FILE__, __LINE__, __PRETTY_FUNCTION__);  \
-                abort();                                                \
+                log_assert(__FILE__, __LINE__, __PRETTY_FUNCTION__,     \
+                           "Code should not be reached '%s' at %s:%u, function %s(). Aborting.", \
+                           t, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
         } while (false)
 
 #define assert_cc(expr)                            \