From: Martin Willi Date: Mon, 1 Jul 2013 16:34:08 +0000 (+0200) Subject: watcher: release threads waiting in remove() when watcher thread gets cancelled X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8acae7143244994bf0f28b975081f10e14a11022;p=thirdparty%2Fstrongswan.git 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. --- diff --git a/src/libstrongswan/processing/watcher.c b/src/libstrongswan/processing/watcher.c index 7ccac72bc1..ff3e116496 100644 --- a/src/libstrongswan/processing/watcher.c +++ b/src/libstrongswan/processing/watcher.c @@ -183,6 +183,28 @@ static bool notify(private_watcher_t *this, entry_t *entry, return TRUE; } +/** + * 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 */ @@ -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))