diff --git a/src/console_commands.cpp b/src/console_commands.cpp
index 48922f77..a0a011e2 100644
--- a/src/console_commands.cpp
+++ b/src/console_commands.cpp
@@ -209,7 +209,7 @@ static void do_status(p2pool *m_pool, const char * /* args */)
 
 	m_pool->print_merge_mining_status();
 
-	bkg_jobs_tracker.print_status();
+	bkg_jobs_tracker->print_status();
 
 	if (p2p) {
 		p2p->check_for_updates(true);
@@ -313,7 +313,7 @@ static void do_stop_mining(p2pool* m_pool, const char* /*args*/)
 
 static void do_exit(p2pool *m_pool, const char * /* args */)
 {
-	bkg_jobs_tracker.wait();
+	bkg_jobs_tracker->wait();
 	m_pool->stop();
 }
 
diff --git a/src/crypto.cpp b/src/crypto.cpp
index 2c1079ac..bf8a6698 100644
--- a/src/crypto.cpp
+++ b/src/crypto.cpp
@@ -37,9 +37,7 @@ class RandomBytes
 public:
 	RandomBytes() : rng(RandomDeviceSeed::instance), dist(0, 255)
 	{
-		if (uv_mutex_init(&m) != 0) {
-			abort();
-		}
+		uv_mutex_init_checked(&m);
 
 		// Diffuse the initial state in case it has low quality
 		rng.discard(10000);
@@ -66,7 +64,7 @@ class RandomBytes
 	std::uniform_int_distribution<> dist;
 };
 
-static RandomBytes randomBytes;
+static RandomBytes* randomBytes = nullptr;
 
 }
 
@@ -86,7 +84,7 @@ static FORCEINLINE bool less32(const uint8_t* k0, const uint8_t* k1)
 void generate_keys(hash& pub, hash& sec)
 {
 	do {
-		do { randomBytes(sec.h); } while (!less32(sec.h, limit));
+		do { (*randomBytes)(sec.h); } while (!less32(sec.h, limit));
 		sc_reduce32(sec.h);
 	} while (!sc_isnonzero(sec.h));
 
@@ -472,6 +470,10 @@ void derive_view_tag(const hash& derivation, size_t output_index, uint8_t& view_
 
 void init_crypto_cache()
 {
+	if (!randomBytes) {
+		randomBytes = new RandomBytes();
+	}
+
 	if (!cache) {
 		cache = new Cache();
 	}
@@ -479,6 +481,11 @@ void init_crypto_cache()
 
 void destroy_crypto_cache()
 {
+	if (randomBytes) {
+		delete randomBytes;
+		randomBytes = nullptr;
+	}
+
 	if (cache) {
 		delete cache;
 		cache = nullptr;
diff --git a/src/log.cpp b/src/log.cpp
index 8d2223ea..f8be07ed 100644
--- a/src/log.cpp
+++ b/src/log.cpp
@@ -122,7 +122,6 @@ class Worker
 	{
 #if defined(_WIN32) && defined(_MSC_VER) && !defined(NDEBUG)
 		SetUnhandledExceptionFilter(UnhandledExceptionFilter);
-		SymInitialize(GetCurrentProcess(), NULL, TRUE);
 #endif
 
 		set_main_thread();
@@ -203,10 +202,6 @@ class Worker
 #endif
 
 		m_logFile.close();
-
-#if defined(_WIN32) && defined(_MSC_VER) && !defined(NDEBUG)
-		SymCleanup(GetCurrentProcess());
-#endif
 	}
 
 	FORCEINLINE void write(const char* buf, uint32_t size)
@@ -398,7 +393,7 @@ class Worker
 	std::ofstream m_logFile;
 };
 
-static Worker worker;
+static Worker* worker = nullptr;
 
 #endif // P2POOL_LOG_DISABLE
 
@@ -445,7 +440,14 @@ NOINLINE Writer::~Writer()
 	m_buf[2] = static_cast<uint8_t>(size >> 8);
 	m_buf[m_pos] = '\n';
 #ifndef P2POOL_LOG_DISABLE
-	worker.write(m_buf, size);
+	worker->write(m_buf, size);
+#endif
+}
+
+void start()
+{
+#ifndef P2POOL_LOG_DISABLE
+	worker = new Worker();
 #endif
 }
 
@@ -458,7 +460,8 @@ void reopen()
 void stop()
 {
 #ifndef P2POOL_LOG_DISABLE
-	worker.stop();
+	delete worker;
+	worker = nullptr;
 #endif
 }
 
diff --git a/src/log.h b/src/log.h
index c1bcc709..a18a630e 100644
--- a/src/log.h
+++ b/src/log.h
@@ -547,6 +547,7 @@ struct DummyStream
 
 #endif
 
+void start();
 void reopen();
 void stop();
 
diff --git a/src/main.cpp b/src/main.cpp
index 4bf34856..748994be 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -188,8 +188,14 @@ int main(int argc, char* argv[])
 		}
 	}
 
+#if defined(_WIN32) && defined(_MSC_VER) && !defined(NDEBUG)
+	SymInitialize(GetCurrentProcess(), NULL, TRUE);
+#endif
+
 	memory_tracking_start();
 
+	p2pool::log::start();
+
 	p2pool::init_crypto_cache();
 
 	int result = static_cast<int>(curl_global_init_mem(CURL_GLOBAL_ALL, p2pool::malloc_hook, p2pool::free_hook, p2pool::realloc_hook, p2pool::strdup_hook, p2pool::calloc_hook));
@@ -209,9 +215,15 @@ int main(int argc, char* argv[])
 
 	p2pool::destroy_crypto_cache();
 
+	p2pool::log::stop();
+
 	if (!memory_tracking_stop()) {
 		result = 1;
 	}
 
+#if defined(_WIN32) && defined(_MSC_VER) && !defined(NDEBUG)
+	SymCleanup(GetCurrentProcess());
+#endif
+
 	return result;
 }
diff --git a/src/memory_leak_debug.cpp b/src/memory_leak_debug.cpp
index 96095846..4015149c 100644
--- a/src/memory_leak_debug.cpp
+++ b/src/memory_leak_debug.cpp
@@ -79,7 +79,7 @@ struct TrackedAllocation
 
 static_assert(sizeof(TrackedAllocation) == 256, "");
 
-uv_mutex_t allocation_lock;
+std::mutex allocation_lock;
 std::hash<void*> hasher;
 uint32_t first[N];
 uint32_t next[N];
@@ -98,7 +98,7 @@ void show_top_10_allocations()
 	const HANDLE h = GetCurrentProcess();
 
 	{
-		p2pool::MutexLock lock(allocation_lock);
+		std::lock_guard<std::mutex> lock(allocation_lock);
 
 		TrackedAllocation* end = buf;
 		for (size_t i = 0; i < N; ++i) {
@@ -173,7 +173,7 @@ FORCEINLINE static void add_alocation(void* p, size_t size)
 
 	const size_t index = hasher(p) & (N - 1);
 
-	p2pool::MutexLock lock(allocation_lock);
+	std::lock_guard<std::mutex> lock(allocation_lock);
 
 	++num_allocations;
 	if (num_allocations >= N / 2) {
@@ -204,7 +204,7 @@ FORCEINLINE static void remove_allocation(void* p)
 		return;
 	}
 
-	p2pool::MutexLock lock(allocation_lock);
+	std::lock_guard<std::mutex> lock(allocation_lock);
 
 	--num_allocations;
 
@@ -295,7 +295,6 @@ void memory_tracking_start()
 	using namespace p2pool;
 
 	uv_replace_allocator(malloc_hook, realloc_hook, calloc_hook, free_hook);
-	uv_mutex_init_checked(&allocation_lock);
 	track_memory = true;
 }
 
@@ -304,7 +303,6 @@ bool memory_tracking_stop()
 	using namespace p2pool;
 
 	track_memory = false;
-	uv_mutex_destroy(&allocation_lock);
 
 	const HANDLE h = GetCurrentProcess();
 
diff --git a/src/p2pool.cpp b/src/p2pool.cpp
index 5fff44fc..9fc5e846 100644
--- a/src/p2pool.cpp
+++ b/src/p2pool.cpp
@@ -161,6 +161,8 @@ p2pool::p2pool(int argc, char* argv[])
 		throw std::exception();
 	}
 
+	bkg_jobs_tracker = new BackgroundJobTracker();
+
 	m_sideChain = new SideChain(this, type, p->m_mini ? "mini" : nullptr);
 
 	if (p->m_p2pAddresses.empty()) {
@@ -184,6 +186,8 @@ p2pool::p2pool(int argc, char* argv[])
 	m_hasher = new RandomX_Hasher_RPC(this);
 #endif
 
+	PoolBlock::s_precalculatedSharesLock = new ReadWriteLock();
+
 	m_blockTemplate = new BlockTemplate(m_sideChain, m_hasher);
 	m_mempool = new Mempool();
 
@@ -232,6 +236,9 @@ p2pool::~p2pool()
 	delete m_blockTemplate;
 	delete m_mempool;
 	delete m_params;
+
+	delete bkg_jobs_tracker;
+	delete PoolBlock::s_precalculatedSharesLock;
 }
 
 void p2pool::update_host_ping(const std::string& display_name, double ping)
@@ -1955,7 +1962,7 @@ int p2pool::run()
 
 	m_stopped = true;
 
-	bkg_jobs_tracker.wait();
+	bkg_jobs_tracker->wait();
 
 #ifdef WITH_RANDOMX
 	delete m_miner;
diff --git a/src/pool_block.cpp b/src/pool_block.cpp
index 2063be26..94bf7bb5 100644
--- a/src/pool_block.cpp
+++ b/src/pool_block.cpp
@@ -29,7 +29,7 @@ LOG_CATEGORY(PoolBlock)
 
 namespace p2pool {
 
-ReadWriteLock PoolBlock::s_precalculatedSharesLock;
+ReadWriteLock* PoolBlock::s_precalculatedSharesLock = nullptr;
 
 PoolBlock::PoolBlock()
 	: m_majorVersion(0)
@@ -118,7 +118,7 @@ PoolBlock& PoolBlock::operator=(const PoolBlock& b)
 	m_wantBroadcast = b.m_wantBroadcast;
 	m_precalculated = b.m_precalculated;
 	{
-		WriteLock lock(s_precalculatedSharesLock);
+		WriteLock lock(*s_precalculatedSharesLock);
 		m_precalculatedShares = b.m_precalculatedShares;
 	}
 
@@ -309,7 +309,7 @@ void PoolBlock::reset_offchain_data()
 
 	m_precalculated = false;
 	{
-		WriteLock lock(s_precalculatedSharesLock);
+		WriteLock lock(*s_precalculatedSharesLock);
 		m_precalculatedShares.clear();
 		m_precalculatedShares.shrink_to_fit();
 	}
diff --git a/src/pool_block.h b/src/pool_block.h
index 866382de..53ace673 100644
--- a/src/pool_block.h
+++ b/src/pool_block.h
@@ -162,7 +162,7 @@ struct PoolBlock
 
 	bool m_precalculated;
 
-	static ReadWriteLock s_precalculatedSharesLock;
+	static ReadWriteLock* s_precalculatedSharesLock;
 	std::vector<MinerShare> m_precalculatedShares;
 
 	uint64_t m_localTimestamp;
diff --git a/src/side_chain.cpp b/src/side_chain.cpp
index 2c615648..57b6c7bb 100644
--- a/src/side_chain.cpp
+++ b/src/side_chain.cpp
@@ -1683,7 +1683,7 @@ void SideChain::verify(PoolBlock* block)
 	std::vector<MinerShare> shares;
 
 	if (block->m_precalculated) {
-		WriteLock lock(PoolBlock::s_precalculatedSharesLock);
+		WriteLock lock(*PoolBlock::s_precalculatedSharesLock);
 		shares = std::move(block->m_precalculatedShares);
 	}
 
@@ -2356,7 +2356,7 @@ void SideChain::launch_precalc(const PoolBlock* block)
 			if (get_shares(b, shares, nullptr, true)) {
 				b->m_precalculated = true;
 				{
-					WriteLock lock(PoolBlock::s_precalculatedSharesLock);
+					WriteLock lock(*PoolBlock::s_precalculatedSharesLock);
 					b->m_precalculatedShares = std::move(shares);
 				}
 				{
@@ -2401,7 +2401,7 @@ void SideChain::precalc_worker()
 
 			wallets.clear();
 
-			ReadLock lock2(PoolBlock::s_precalculatedSharesLock);
+			ReadLock lock2(*PoolBlock::s_precalculatedSharesLock);
 
 			const size_t n = job->m_precalculatedShares.size();
 
diff --git a/src/util.cpp b/src/util.cpp
index 137dafc0..b4f3271e 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -452,7 +452,7 @@ void BackgroundJobTracker::print_status()
 	m_impl->print_status();
 }
 
-BackgroundJobTracker bkg_jobs_tracker;
+BackgroundJobTracker* bkg_jobs_tracker = nullptr;
 
 static thread_local bool main_thread = false;
 void set_main_thread() { main_thread = true; }
diff --git a/src/util.h b/src/util.h
index 27d150d2..f531e227 100644
--- a/src/util.h
+++ b/src/util.h
@@ -233,10 +233,10 @@ class BackgroundJobTracker : public nocopy_nomove
 	Impl* m_impl;
 };
 
-extern BackgroundJobTracker bkg_jobs_tracker;
+extern BackgroundJobTracker* bkg_jobs_tracker;
 
-#define BACKGROUND_JOB_START(x) do { bkg_jobs_tracker.start(#x); } while (0)
-#define BACKGROUND_JOB_STOP(x)  do { bkg_jobs_tracker.stop(#x);  } while (0)
+#define BACKGROUND_JOB_START(x) do { bkg_jobs_tracker->start(#x); } while (0)
+#define BACKGROUND_JOB_STOP(x)  do { bkg_jobs_tracker->stop(#x);  } while (0)
 
 void set_main_thread();
 bool is_main_thread();
diff --git a/tests/src/main.cpp b/tests/src/main.cpp
index 020ca330..8a240e3c 100644
--- a/tests/src/main.cpp
+++ b/tests/src/main.cpp
@@ -15,14 +15,26 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "common.h"
+#include "util.h"
+#include "pool_block.h"
+
 #include "gtest/gtest.h"
 
 void p2pool_usage() {}
-namespace p2pool { void set_main_thread(); }
+
+using namespace p2pool;
 
 int main(int argc, char** argv)
 {
-	p2pool::set_main_thread();
+	set_main_thread();
+
+	PoolBlock::s_precalculatedSharesLock = new ReadWriteLock();
+
 	testing::InitGoogleTest(&argc, argv);
-	return RUN_ALL_TESTS();
+	const int result = RUN_ALL_TESTS();
+
+	delete PoolBlock::s_precalculatedSharesLock;
+
+	return result;
 }