stream-service: Restart accepting without blocking

Calling on_accept() sometimes lead to deadlocks when service->destroy()
was called concurrently.  That is, two threads waiting in on_accept() but
the last worker would only wake one due to the call to signal().  Calling
broadcast() wouldn't help either as that could lead to crashes if the thread
that called destroy() is woken first.

This is also more efficient as a constant pool of concurrent workers can
be maintained, otherwise peaks at the limit were followed by only a single
worker being active.
This commit is contained in:
Tobias Brunner
2014-09-09 10:58:58 +02:00
parent e58764ca0f
commit 22e90cad00
@@ -92,6 +92,11 @@ typedef struct {
private_stream_service_t *this;
} async_data_t;
/**
* Forward declaration
*/
static bool watch(private_stream_service_t *this, int fd, watcher_event_t event);
/**
* Clean up accept data
*/
@@ -103,8 +108,8 @@ static void destroy_async_data(async_data_t *data)
if (this->active-- == this->cncrncy)
{
/* leaving concurrency limit, restart accept()ing. */
this->public.on_accept(&this->public, this->cb, this->data,
this->prio, this->cncrncy);
lib->watcher->add(lib->watcher, this->fd,
WATCHER_READ, (watcher_cb_t)watch, this);
}
this->condvar->signal(this->condvar);
this->mutex->unlock(this->mutex);