aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorj-berman <justinberman@protonmail.com>2025-11-07 16:00:57 -0800
committerj-berman <justinberman@protonmail.com>2025-11-11 10:44:26 -0800
commita83a46d60059a063ec953ba15f4cdcc2b3874440 (patch)
treea152e55dfff1e3b4a84dd83ae8648d15e189a21d /tests
parent3cc9d65c9374b541e64320052c933184944375ea (diff)
downloadmonzero-core-a83a46d60059a063ec953ba15f4cdcc2b3874440.tar.gz
monzero-core-a83a46d60059a063ec953ba15f4cdcc2b3874440.tar.xz
monzero-core-a83a46d60059a063ec953ba15f4cdcc2b3874440.zip
Fix logging deadlock
Diffstat (limited to 'tests')
-rw-r--r--tests/unit_tests/logging.cpp56
1 files changed, 56 insertions, 0 deletions
diff --git a/tests/unit_tests/logging.cpp b/tests/unit_tests/logging.cpp
index 2c10f2c0a..371f18812 100644
--- a/tests/unit_tests/logging.cpp
+++ b/tests/unit_tests/logging.cpp
@@ -28,6 +28,10 @@
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+
#include <boost/filesystem.hpp>
#include "gtest/gtest.h"
#include "file_io_utils.h"
@@ -215,3 +219,55 @@ TEST(logging, empty_configurations_throws)
const el::Configurations cfg;
EXPECT_ANY_THROW(log1.configure(cfg));
}
+
+TEST(logging, deadlock)
+{
+ std::mutex inner_mutex;
+
+ // 1. Thread 1 starts logger
+ // 2. Thread 2 grabs inner mutex shared across threads
+ // 3. Thread 2 logs
+ // 4. Thread 1 grabs inner mutex shared across threads
+ // 5. Thread 1 finishes logging
+ std::condition_variable cv1, cv2;
+ std::mutex mutex1, mutex2;
+ std::unique_lock<std::mutex> lock_until_t1_starts_logger(mutex1);
+ std::unique_lock<std::mutex> lock_until_t2_finishes_logging(mutex2);
+ bool t1_started_logger = false;
+ bool t2_finished_logging = false;
+
+ const auto thread1_func = [&]
+ {
+ const auto thread1_inner_func = [&]() -> std::string
+ {
+ t1_started_logger = true;
+ lock_until_t1_starts_logger.unlock();
+ cv1.notify_one();
+ cv2.wait(lock_until_t2_finishes_logging, [&]{return t2_finished_logging;});
+
+ std::lock_guard<std::mutex> guard(inner_mutex);
+ return "world!";
+ };
+ MGINFO("Hello, " << thread1_inner_func() << " - Sincerely, thread 1");
+ };
+
+ const auto thread2_func = [&]
+ {
+ cv1.wait(lock_until_t1_starts_logger, [&]{return t1_started_logger;});
+
+ {
+ std::lock_guard<std::mutex> guard(inner_mutex);
+ MGINFO("Hello, world! - Sincerely, thread 2");
+ }
+
+ t2_finished_logging = true;
+ lock_until_t2_finishes_logging.unlock();
+ cv2.notify_one();
+ };
+
+ std::thread t1(thread1_func);
+ std::thread t2(thread2_func);
+
+ t1.join();
+ t2.join();
+}