From 9dec601f30ca6558c1b070de1d8e1a2a43eaf49e Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 28 May 2014 17:34:48 +0200 Subject: windows: Prevent queueing of multiple thread cancel APCs This avoids any races during cleanup invocation if multiple cancel() requests come in. --- src/libstrongswan/threading/windows/thread.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src/libstrongswan/threading/windows/thread.c') diff --git a/src/libstrongswan/threading/windows/thread.c b/src/libstrongswan/threading/windows/thread.c index 71e56528e..5fa68bb91 100644 --- a/src/libstrongswan/threading/windows/thread.c +++ b/src/libstrongswan/threading/windows/thread.c @@ -88,10 +88,15 @@ struct private_thread_t { bool cancelability; /** - * Has the thread been cancelled + * Has the thread been cancelled by thread->cancel()? */ bool canceled; + /** + * Did we schedule an APC to docancel()? + */ + bool cancel_pending; + /** * Active condition variable thread is waiting in, if any */ @@ -357,10 +362,14 @@ METHOD(thread_t, cancel, void, if (this->cancelability) { threads_lock->lock(threads_lock); - QueueUserAPC((void*)docancel, this->handle, (uintptr_t)this); - if (this->condvar) + if (!this->cancel_pending) { - WakeAllConditionVariable(this->condvar); + this->cancel_pending = TRUE; + QueueUserAPC((void*)docancel, this->handle, (uintptr_t)this); + if (this->condvar) + { + WakeAllConditionVariable(this->condvar); + } } threads_lock->unlock(threads_lock); } -- cgit v1.2.3