fix(util/interrupt): fix nasty bug on interruptible_thread, it seems to occur only on cygwin
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
c22f863114
commit
4eb62fef91
1 changed files with 16 additions and 0 deletions
|
@ -43,6 +43,21 @@ void sleep_for(unsigned ms, unsigned step_ms = g_small_sleep);
|
||||||
*/
|
*/
|
||||||
class interruptible_thread {
|
class interruptible_thread {
|
||||||
std::atomic<std::atomic_bool*> m_flag_addr;
|
std::atomic<std::atomic_bool*> 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;
|
std::thread m_thread;
|
||||||
static std::atomic_bool * get_flag_addr();
|
static std::atomic_bool * get_flag_addr();
|
||||||
public:
|
public:
|
||||||
|
@ -53,6 +68,7 @@ public:
|
||||||
[&](Function&& fun, Args&&... args) {
|
[&](Function&& fun, Args&&... args) {
|
||||||
m_flag_addr.store(get_flag_addr());
|
m_flag_addr.store(get_flag_addr());
|
||||||
fun(std::forward<Args>(args)...);
|
fun(std::forward<Args>(args)...);
|
||||||
|
m_flag_addr.store(&m_dummy_addr); // see comment before m_dummy_addr
|
||||||
},
|
},
|
||||||
std::forward<Function>(fun),
|
std::forward<Function>(fun),
|
||||||
std::forward<Args>(args)...)
|
std::forward<Args>(args)...)
|
||||||
|
|
Loading…
Reference in a new issue