From 502e7bb39096f6ce7718c29d9616bbd0314d045e Mon Sep 17 00:00:00 2001 From: dimitri staessens Date: Wed, 28 Dec 2016 09:05:44 +0100 Subject: lib: Fix race in destruction of cdap_req If cdap_req_destroy was called while in REQ_DONE, cdap->state would be accessed in cdap_req_respond. --- src/lib/cdap_req.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'src/lib/cdap_req.c') diff --git a/src/lib/cdap_req.c b/src/lib/cdap_req.c index f80b10d7..57ad22c5 100644 --- a/src/lib/cdap_req.c +++ b/src/lib/cdap_req.c @@ -70,14 +70,14 @@ void cdap_req_destroy(struct cdap_req * creq) } if (creq->state == REQ_INIT) - creq->state = REQ_DONE; + creq->state = REQ_NULL; if (creq->state == REQ_PENDING) { creq->state = REQ_DESTROY; pthread_cond_broadcast(&creq->cond); } - while (creq->state != REQ_DONE) + while (creq->state != REQ_NULL) pthread_cond_wait(&creq->cond, &creq->lock); pthread_mutex_unlock(&creq->lock); @@ -109,17 +109,21 @@ int cdap_req_wait(struct cdap_req * creq) creq->state = REQ_PENDING; while (creq->state == REQ_PENDING) { - if ((ret = -pthread_cond_timedwait(&creq->cond, - &creq->lock, - &abstime)) == -ETIMEDOUT) + ret = -pthread_cond_timedwait(&creq->cond, + &creq->lock, + &abstime); + if (ret == -ETIMEDOUT) break; } - if (creq->state == REQ_DESTROY) + if (creq->state == REQ_DESTROY) { ret = -1; - - creq->state = REQ_DONE; - pthread_cond_broadcast(&creq->cond); + creq->state = REQ_NULL; + pthread_cond_broadcast(&creq->cond); + } else { + creq->state = REQ_DONE; + pthread_cond_broadcast(&creq->cond); + } pthread_mutex_unlock(&creq->lock); @@ -146,5 +150,8 @@ void cdap_req_respond(struct cdap_req * creq, int response, buffer_t data) while (creq->state == REQ_RESPONSE) pthread_cond_wait(&creq->cond, &creq->lock); + creq->state = REQ_NULL; + pthread_cond_broadcast(&creq->cond); + pthread_mutex_unlock(&creq->lock); } -- cgit v1.2.3