aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2014-07-21 11:30:34 +0200
committerTobias Brunner <tobias@strongswan.org>2014-09-09 10:58:58 +0200
commit22e90cad00c59d723a2edbf953d5e250e0462022 (patch)
treefb792a1229cba9fc57d9280cac0b9d17bff83f2b /src
parente58764ca0f5996c8236cb11c71ff586fb97f47b9 (diff)
downloadstrongswan-22e90cad00c59d723a2edbf953d5e250e0462022.tar.bz2
strongswan-22e90cad00c59d723a2edbf953d5e250e0462022.tar.xz
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.
Diffstat (limited to 'src')
-rw-r--r--src/libstrongswan/networking/streams/stream_service.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/src/libstrongswan/networking/streams/stream_service.c b/src/libstrongswan/networking/streams/stream_service.c
index 7358c580e..07d9cfdef 100644
--- a/src/libstrongswan/networking/streams/stream_service.c
+++ b/src/libstrongswan/networking/streams/stream_service.c
@@ -93,6 +93,11 @@ typedef struct {
} async_data_t;
/**
+ * Forward declaration
+ */
+static bool watch(private_stream_service_t *this, int fd, watcher_event_t event);
+
+/**
* Clean up accept data
*/
static void destroy_async_data(async_data_t *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);