aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan/processing
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2013-07-01 18:34:08 +0200
committerMartin Willi <martin@revosec.ch>2013-07-18 16:00:29 +0200
commita558ba16f314d250ef62a593e66e263123a0e9a3 (patch)
tree19d66cccf63919a0a4bc4636cbdbd63a8bc62fb4 /src/libstrongswan/processing
parente6e8a2b2e01e91f75048fd4a33e04a0a7612bd12 (diff)
downloadstrongswan-a558ba16f314d250ef62a593e66e263123a0e9a3.tar.bz2
strongswan-a558ba16f314d250ef62a593e66e263123a0e9a3.tar.xz
watcher: release threads waiting in remove() when watcher thread gets cancelled
During daemon shutdown, users might call remove() after processor.set_threads(0) has been called. This gets problematic, as a watch event might be unable to signal completion when no threads are available anymore. Work around this issue by cancelling waiters once processor.cancel() has been called.
Diffstat (limited to 'src/libstrongswan/processing')
-rw-r--r--src/libstrongswan/processing/watcher.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/libstrongswan/processing/watcher.c b/src/libstrongswan/processing/watcher.c
index 7ccac72bc..ff3e11649 100644
--- a/src/libstrongswan/processing/watcher.c
+++ b/src/libstrongswan/processing/watcher.c
@@ -184,6 +184,28 @@ static bool notify(private_watcher_t *this, entry_t *entry,
}
/**
+ * Thread cancellation function for watcher thread
+ */
+static void activate_all(private_watcher_t *this)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+
+ /* When the watcher thread gets cancelled, we have to reactivate any entry
+ * and signal threads in remove() to go on. */
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->fds->create_enumerator(this->fds);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ entry->active = TRUE;
+ }
+ enumerator->destroy(enumerator);
+ this->condvar->broadcast(this->condvar);
+ this->mutex->unlock(this->mutex);
+}
+
+/**
* Dispatching function
*/
static job_requeue_t watch(private_watcher_t *this)
@@ -238,9 +260,11 @@ static job_requeue_t watch(private_watcher_t *this)
char buf[1];
bool old, notified = FALSE;
+ thread_cleanup_push((void*)activate_all, this);
old = thread_cancelability(TRUE);
res = select(maxfd + 1, &rd, &wr, &ex, NULL);
thread_cancelability(old);
+ thread_cleanup_pop(FALSE);
if (res > 0)
{
if (this->notify[0] != -1 && FD_ISSET(this->notify[0], &rd))