From 4eb62fef913448b12cd72b1ea16a9569b141d5b5 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 25 Nov 2013 17:10:01 -0800 Subject: [PATCH] fix(util/interrupt): fix nasty bug on interruptible_thread, it seems to occur only on cygwin Signed-off-by: Leonardo de Moura --- src/util/interrupt.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/util/interrupt.h b/src/util/interrupt.h index c1f64c530..2e634b04e 100644 --- a/src/util/interrupt.h +++ b/src/util/interrupt.h @@ -43,6 +43,21 @@ void sleep_for(unsigned ms, unsigned step_ms = g_small_sleep); */ class interruptible_thread { std::atomic m_flag_addr; + /* + The following auxiliary field is used to workaround + a nasty bug that occurs in some platforms. + On cygwin, it seems that the thread local storage is + deleted before the object m_thread is destructed. + Then, the main thread may corrupt memory if it invokes + request_interrupt after the child thread referenced + by m_thread has terminated. + The method request_interrupt access the child thread + local storage pointed by m_flag_addr. + To avoid this bug, we use the a simple hack, + we reset m_flag_addr to m_dummy_addr before terminating + the execution of the main thread. + */ + std::atomic_bool m_dummy_addr; std::thread m_thread; static std::atomic_bool * get_flag_addr(); public: @@ -53,6 +68,7 @@ public: [&](Function&& fun, Args&&... args) { m_flag_addr.store(get_flag_addr()); fun(std::forward(args)...); + m_flag_addr.store(&m_dummy_addr); // see comment before m_dummy_addr }, std::forward(fun), std::forward(args)...)