Skip to content

Commit 24ed5fd

Browse files
committed
fix(core): resolve TSAN data race in start_timeout_timer weak_ptr destruction
Release state_weak explicitly while the strong reference s is still alive to prevent a ThreadSanitizer-detected data race on the shared_ptr control block. Previously, the captured weak_ptr was destroyed as part of the lambda closure after s went out of scope, causing a concurrent operator delete (from ~weak_ptr on zero weak count) to race with the token destructor's __release_shared read on the same control block address. By calling state_weak.reset() before s is released, the weak ref-count decrement occurs while a strong reference still exists, ensuring the control block is freed deterministically on the main thread rather than racing with the timer thread. Fixes: ThreadSanitizer warning in enhanced_cancellation_token_test.LinkedWithTimeoutParentCancel
1 parent d084254 commit 24ed5fd

1 file changed

Lines changed: 8 additions & 1 deletion

File tree

src/core/enhanced_cancellation_token.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ namespace kcenon::thread
476476
std::chrono::steady_clock::time_point deadline_point) -> void
477477
{
478478
std::thread timer_thread(
479-
[state_weak, deadline_point]()
479+
[state_weak, deadline_point]() mutable
480480
{
481481
auto s = state_weak.lock();
482482
if (!s)
@@ -544,6 +544,13 @@ namespace kcenon::thread
544544
}
545545

546546
s->timer_active.store(false, std::memory_order_release);
547+
548+
// Release the weak_ptr while the strong reference (s) is still alive.
549+
// This ensures ~weak_ptr() decrements the weak ref-count before the
550+
// last shared_ptr is released, preventing a data race on the control
551+
// block between this thread's operator delete and the token destructor's
552+
// __release_shared read (ThreadSanitizer: data race).
553+
state_weak.reset();
547554
});
548555

549556
timer_thread.detach();

0 commit comments

Comments
 (0)