mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
macro: flip ONCE macro to make log_once() and friend actually log once
Previously, ONCE is false for the first time, and true for later times, hence log_once() and log_once_errno() suppress logging in the first call, rather than later calls. Fortunately, ONCE macro is only used in log_once() and log_once_errno(), hence this only fixes spurious logging.
This commit is contained in:
committed by
Daan De Meyer
parent
444af9538f
commit
acd33c5df8
@@ -144,15 +144,15 @@
|
||||
#define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
|
||||
#define UNIQ __COUNTER__
|
||||
|
||||
/* Note that this works differently from pthread_once(): this macro does
|
||||
* not synchronize code execution, i.e. code that is run conditionalized
|
||||
* on this macro will run concurrently to all other code conditionalized
|
||||
* the same way, there's no ordering or completion enforced. */
|
||||
/* The macro is true when the code block is called first time, and is false for the second and later times.
|
||||
* Note that this works differently from pthread_once(): this macro does not synchronize code execution, i.e.
|
||||
* code that is run conditionalized on this macro will run concurrently to all other code conditionalized the
|
||||
* same way, there's no ordering or completion enforced. */
|
||||
#define ONCE __ONCE(UNIQ_T(_once_, UNIQ))
|
||||
#define __ONCE(o) \
|
||||
({ \
|
||||
static bool (o) = false; \
|
||||
__atomic_exchange_n(&(o), true, __ATOMIC_SEQ_CST); \
|
||||
#define __ONCE(o) \
|
||||
({ \
|
||||
static bool (o) = false; \
|
||||
!__atomic_exchange_n(&(o), true, __ATOMIC_SEQ_CST); \
|
||||
})
|
||||
|
||||
#define U64_KB UINT64_C(1024)
|
||||
|
||||
@@ -42,6 +42,22 @@ static void test_file(void) {
|
||||
assert_se(startswith(__FILE__, RELATIVE_SOURCE_PATH "/"));
|
||||
}
|
||||
|
||||
static void test_log_once_impl(void) {
|
||||
log_once(LOG_INFO, "This should be logged in LOG_INFO at first, then in LOG_DEBUG later.");
|
||||
log_once(LOG_DEBUG, "This should be logged only once in LOG_DEBUG.");
|
||||
ASSERT_ERROR(log_once_errno(LOG_INFO, SYNTHETIC_ERRNO(ENOANO),
|
||||
"This should be logged with errno in LOG_INFO at first, then in LOG_DEBUG later: %m"),
|
||||
ENOANO);
|
||||
ASSERT_ERROR(log_once_errno(LOG_DEBUG, SYNTHETIC_ERRNO(EBADMSG),
|
||||
"This should be logged only once with errno in LOG_DEBUG: %m"),
|
||||
EBADMSG);
|
||||
}
|
||||
|
||||
static void test_log_once(void) {
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
test_log_once_impl();
|
||||
}
|
||||
|
||||
static void test_log_struct(void) {
|
||||
log_struct(LOG_INFO,
|
||||
"MESSAGE=Waldo PID="PID_FMT" (no errno)", getpid_cached(),
|
||||
@@ -233,6 +249,8 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
assert_se(log_info_errno(SYNTHETIC_ERRNO(EUCLEAN), "foo") == -EUCLEAN);
|
||||
|
||||
test_log_once();
|
||||
|
||||
for (int target = 0; target < _LOG_TARGET_MAX; target++) {
|
||||
log_set_target(target);
|
||||
log_open();
|
||||
|
||||
@@ -1102,4 +1102,20 @@ TEST(u64_multiply_safe) {
|
||||
assert_se(u64_multiply_safe(UINT64_MAX, UINT64_MAX) == 0);
|
||||
}
|
||||
|
||||
static void test_once_impl(void) {
|
||||
static unsigned count = 0;
|
||||
|
||||
if (ONCE) {
|
||||
log_info("This should be logged only once.");
|
||||
count++;
|
||||
}
|
||||
|
||||
ASSERT_EQ(count, 1u);
|
||||
}
|
||||
|
||||
TEST(once) {
|
||||
for (unsigned i = 0; i < 20; i++)
|
||||
test_once_impl();
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
|
||||
Reference in New Issue
Block a user