]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
watcher: release threads waiting in remove() when watcher thread gets cancelled
authorMartin Willi <martin@revosec.ch>
Mon, 1 Jul 2013 16:34:08 +0000 (18:34 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 17 Jul 2013 14:55:48 +0000 (16:55 +0200)
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.

src/libstrongswan/processing/watcher.c

index 7ccac72bc17c321ccdb79e7fee19970acb036236..ff3e1164963bcfb29d691a00ede1497197016b45 100644 (file)
@@ -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))