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.
This commit is contained in:
Martin Willi
2013-07-18 16:00:29 +02:00
parent e6e8a2b2e0
commit a558ba16f3
+24
View 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))