/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include #include #include "assert-util.h" #include "env-util.h" #include "errno-util.h" #include "log.h" static bool assert_return_is_critical = BUILD_MODE_DEVELOPER; /* Akin to glibc's __abort_msg; which is private and we hence cannot * use here. */ static char *log_abort_msg = NULL; void log_set_assert_return_is_critical(bool b) { assert_return_is_critical = b; } void log_set_assert_return_is_critical_from_env(void) { static int cached = INT_MIN; int r; if (cached == INT_MIN) { r = secure_getenv_bool("SYSTEMD_ASSERT_RETURN_IS_CRITICAL"); if (r < 0 && r != -ENXIO) log_debug_errno(r, "Failed to parse $SYSTEMD_ASSERT_RETURN_IS_CRITICAL, ignoring: %m"); cached = r; } if (cached >= 0) log_set_assert_return_is_critical(cached); } bool log_get_assert_return_is_critical(void) { return assert_return_is_critical; } static void log_assert( int level, const char *text, const char *file, int line, const char *func, const char *format) { static char buffer[LINE_MAX]; if (_likely_(LOG_PRI(level) > log_get_max_level())) return; DISABLE_WARNING_FORMAT_NONLITERAL; (void) snprintf(buffer, sizeof buffer, format, text, file, line, func); REENABLE_WARNING; log_abort_msg = buffer; log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer); } _noreturn_ void log_assert_failed(const char *text, const char *file, int line, const char *func) { log_assert(LOG_CRIT, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(). Aborting."); abort(); } _noreturn_ void log_assert_failed_unreachable(const char *file, int line, const char *func) { log_assert(LOG_CRIT, "Code should not be reached", file, line, func, "%s at %s:%u, function %s(). Aborting. 💥"); abort(); } void log_assert_failed_return(const char *text, const char *file, int line, const char *func) { if (assert_return_is_critical) log_assert_failed(text, file, line, func); PROTECT_ERRNO; log_assert(LOG_DEBUG, text, file, line, func, "Assertion '%s' failed at %s:%u, function %s(), ignoring."); }