Skip to content

Commit 03e17cb

Browse files
committed
basic: Move assertion specific functions to assert-util.h
Various functions in log.h are only used by asserts, and there's enough assertion related stuff in macro.h to justify a separate header which also makes it easier to avoid circular dependencies. Let's introduce assert-util.h and an accompanying fundamental header and move all the assertion related stuff over there. PROJECT_FILE is moved over to macro.h.
1 parent edfd847 commit 03e17cb

27 files changed

+218
-196
lines changed

src/basic/alloc-util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <stdlib.h>
88
#include <string.h>
99

10+
#include "assert-util.h"
1011
#include "macro.h"
1112

1213
#if HAS_FEATURE_MEMORY_SANITIZER

src/basic/argv-util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <stdbool.h>
55

6+
#include "assert-util.h"
67
#include "macro.h"
78

89
extern int saved_argc;

src/basic/assert-util.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2+
3+
#include <stdio.h>
4+
5+
#include "assert-util.h"
6+
#include "errno-util.h"
7+
#include "log.h"
8+
9+
static bool assert_return_is_critical = BUILD_MODE_DEVELOPER;
10+
11+
/* Akin to glibc's __abort_msg; which is private and we hence cannot
12+
* use here. */
13+
static char *log_abort_msg = NULL;
14+
15+
void log_set_assert_return_is_critical(bool b) {
16+
assert_return_is_critical = b;
17+
}
18+
19+
bool log_get_assert_return_is_critical(void) {
20+
return assert_return_is_critical;
21+
}
22+
23+
static void log_assert(
24+
int level,
25+
const char *text,
26+
const char *file,
27+
int line,
28+
const char *func,
29+
const char *format) {
30+
31+
static char buffer[LINE_MAX];
32+
33+
if (_likely_(LOG_PRI(level) > log_get_max_level()))
34+
return;
35+
36+
DISABLE_WARNING_FORMAT_NONLITERAL;
37+
(void) snprintf(buffer, sizeof buffer, format, text, file, line, func);
38+
REENABLE_WARNING;
39+
40+
log_abort_msg = buffer;
41+
42+
log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
43+
}
44+
45+
_noreturn_ void log_assert_failed(const char *text, const char *file, int line, const char *func) {
46+
log_assert(LOG_CRIT, text, file, line, func,
47+
"Assertion '%s' failed at %s:%u, function %s(). Aborting.");
48+
abort();
49+
}
50+
51+
_noreturn_ void log_assert_failed_unreachable(const char *file, int line, const char *func) {
52+
log_assert(LOG_CRIT, "Code should not be reached", file, line, func,
53+
"%s at %s:%u, function %s(). Aborting. 💥");
54+
abort();
55+
}
56+
57+
void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
58+
59+
if (assert_return_is_critical)
60+
log_assert_failed(text, file, line, func);
61+
62+
PROTECT_ERRNO;
63+
log_assert(LOG_DEBUG, text, file, line, func,
64+
"Assertion '%s' failed at %s:%u, function %s(), ignoring.");
65+
}

src/basic/assert-util.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2+
#pragma once
3+
4+
#include "assert-fundamental.h"
5+
#include "macro.h"
6+
7+
/* Logging for various assertions */
8+
9+
void log_set_assert_return_is_critical(bool b);
10+
bool log_get_assert_return_is_critical(void) _pure_;
11+
12+
_noreturn_ void log_assert_failed(const char *text, const char *file, int line, const char *func);
13+
_noreturn_ void log_assert_failed_unreachable(const char *file, int line, const char *func);
14+
void log_assert_failed_return(const char *text, const char *file, int line, const char *func);
15+
16+
#ifdef __COVERITY__
17+
18+
/* Use special definitions of assertion macros in order to prevent
19+
* false positives of ASSERT_SIDE_EFFECT on Coverity static analyzer
20+
* for uses of assert_se() and assert_return().
21+
*
22+
* These definitions make expression go through a (trivial) function
23+
* call to ensure they are not discarded. Also use ! or !! to ensure
24+
* the boolean expressions are seen as such.
25+
*
26+
* This technique has been described and recommended in:
27+
* https://community.synopsys.com/s/question/0D534000046Yuzb/suppressing-assertsideeffect-for-functions-that-allow-for-sideeffects
28+
*/
29+
30+
extern void __coverity_panic__(void);
31+
32+
static inline void __coverity_check__(int condition) {
33+
if (!condition)
34+
__coverity_panic__();
35+
}
36+
37+
static inline int __coverity_check_and_return__(int condition) {
38+
return condition;
39+
}
40+
41+
#define assert_message_se(expr, message) __coverity_check__(!!(expr))
42+
43+
#define assert_log(expr, message) __coverity_check_and_return__(!!(expr))
44+
45+
#else /* ! __COVERITY__ */
46+
47+
#define assert_message_se(expr, message) \
48+
do { \
49+
if (_unlikely_(!(expr))) \
50+
log_assert_failed(message, PROJECT_FILE, __LINE__, __func__); \
51+
} while (false)
52+
53+
#define assert_log(expr, message) ((_likely_(expr)) \
54+
? (true) \
55+
: (log_assert_failed_return(message, PROJECT_FILE, __LINE__, __func__), false))
56+
57+
#endif /* __COVERITY__ */
58+
59+
#define assert_se(expr) assert_message_se(expr, #expr)
60+
61+
/* We override the glibc assert() here. */
62+
#undef assert
63+
#ifdef NDEBUG
64+
#define assert(expr) ({ if (!(expr)) __builtin_unreachable(); })
65+
#else
66+
#define assert(expr) assert_message_se(expr, #expr)
67+
#endif
68+
69+
#define assert_not_reached() \
70+
log_assert_failed_unreachable(PROJECT_FILE, __LINE__, __func__)
71+
72+
#define assert_return(expr, r) \
73+
do { \
74+
if (!assert_log(expr, #expr)) \
75+
return (r); \
76+
} while (false)
77+
78+
#define assert_return_errno(expr, r, err) \
79+
do { \
80+
if (!assert_log(expr, #expr)) { \
81+
errno = err; \
82+
return (r); \
83+
} \
84+
} while (false)

src/basic/dlfcn-util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <dlfcn.h>
55

6+
#include "assert-util.h"
67
#include "macro.h"
78

89
static inline void* safe_dlclose(void *dl) {

src/basic/errno-util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <stdlib.h>
66
#include <string.h>
77

8+
#include "assert-util.h"
89
#include "macro.h"
910

1011
/* strerror(3) says that glibc uses a maximum length of 1024 bytes. */

src/basic/log.c

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,6 @@ static bool upgrade_syslog_to_journal = false;
7878
static bool always_reopen_console = false;
7979
static bool open_when_needed = false;
8080
static bool prohibit_ipc = false;
81-
static bool assert_return_is_critical = BUILD_MODE_DEVELOPER;
82-
83-
/* Akin to glibc's __abort_msg; which is private and we hence cannot
84-
* use here. */
85-
static char *log_abort_msg = NULL;
8681

8782
static thread_local const char *log_prefix = NULL;
8883

@@ -950,61 +945,6 @@ int log_object_internal(
950945
return r;
951946
}
952947

953-
static void log_assert(
954-
int level,
955-
const char *text,
956-
const char *file,
957-
int line,
958-
const char *func,
959-
const char *format) {
960-
961-
static char buffer[LINE_MAX];
962-
963-
if (_likely_(LOG_PRI(level) > log_max_level))
964-
return;
965-
966-
DISABLE_WARNING_FORMAT_NONLITERAL;
967-
(void) snprintf(buffer, sizeof buffer, format, text, file, line, func);
968-
REENABLE_WARNING;
969-
970-
log_abort_msg = buffer;
971-
972-
log_dispatch_internal(level, 0, file, line, func, NULL, NULL, NULL, NULL, buffer);
973-
}
974-
975-
_noreturn_ void log_assert_failed(
976-
const char *text,
977-
const char *file,
978-
int line,
979-
const char *func) {
980-
log_assert(LOG_CRIT, text, file, line, func,
981-
"Assertion '%s' failed at %s:%u, function %s(). Aborting.");
982-
abort();
983-
}
984-
985-
_noreturn_ void log_assert_failed_unreachable(
986-
const char *file,
987-
int line,
988-
const char *func) {
989-
log_assert(LOG_CRIT, "Code should not be reached", file, line, func,
990-
"%s at %s:%u, function %s(). Aborting. 💥");
991-
abort();
992-
}
993-
994-
void log_assert_failed_return(
995-
const char *text,
996-
const char *file,
997-
int line,
998-
const char *func) {
999-
1000-
if (assert_return_is_critical)
1001-
log_assert_failed(text, file, line, func);
1002-
1003-
PROTECT_ERRNO;
1004-
log_assert(LOG_DEBUG, text, file, line, func,
1005-
"Assertion '%s' failed at %s:%u, function %s(), ignoring.");
1006-
}
1007-
1008948
int log_oom_internal(int level, const char *file, int line, const char *func) {
1009949
return log_internal(level, ENOMEM, file, line, func, "Out of memory.");
1010950
}
@@ -1318,14 +1258,6 @@ static int log_set_ratelimit_kmsg_from_string(const char *e) {
13181258
return 0;
13191259
}
13201260

1321-
void log_set_assert_return_is_critical(bool b) {
1322-
assert_return_is_critical = b;
1323-
}
1324-
1325-
bool log_get_assert_return_is_critical(void) {
1326-
return assert_return_is_critical;
1327-
}
1328-
13291261
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
13301262

13311263
/*

src/basic/log.h

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ int log_show_tid_from_string(const char *e);
7979
* environment should not be called from library code — this is always a job
8080
* for the application itself. */
8181

82-
assert_cc(STRLEN(__FILE__) > STRLEN(RELATIVE_SOURCE_PATH) + 1);
83-
#define PROJECT_FILE (&__FILE__[STRLEN(RELATIVE_SOURCE_PATH) + 1])
84-
8582
bool stderr_is_journal(void);
8683
int log_open(void);
8784
void log_close(void);
@@ -185,24 +182,6 @@ int log_dump_internal(
185182
const char *func,
186183
char *buffer);
187184

188-
/* Logging for various assertions */
189-
_noreturn_ void log_assert_failed(
190-
const char *text,
191-
const char *file,
192-
int line,
193-
const char *func);
194-
195-
_noreturn_ void log_assert_failed_unreachable(
196-
const char *file,
197-
int line,
198-
const char *func);
199-
200-
void log_assert_failed_return(
201-
const char *text,
202-
const char *file,
203-
int line,
204-
const char *func);
205-
206185
#define log_dispatch(level, error, buffer) \
207186
log_dispatch_internal(level, error, PROJECT_FILE, __LINE__, __func__, NULL, NULL, NULL, NULL, buffer)
208187

@@ -336,9 +315,6 @@ void log_set_open_when_needed(bool b);
336315
* stderr, the console or kmsg */
337316
void log_set_prohibit_ipc(bool b);
338317

339-
void log_set_assert_return_is_critical(bool b);
340-
bool log_get_assert_return_is_critical(void) _pure_;
341-
342318
int log_dup_console(void);
343319

344320
int log_syntax_internal(

0 commit comments

Comments
 (0)