summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordimitri staessens <dimitri.staessens@intec.ugent.be>2016-12-28 09:05:44 +0100
committerdimitri staessens <dimitri.staessens@intec.ugent.be>2016-12-28 09:15:46 +0100
commit502e7bb39096f6ce7718c29d9616bbd0314d045e (patch)
treecfa8af4328890f3534adc17c1f1ee8be67331cc3
parent6d14473d4fd0629125d9a96d9292deb32ba7e0a8 (diff)
downloadouroboros-502e7bb39096f6ce7718c29d9616bbd0314d045e.tar.gz
ouroboros-502e7bb39096f6ce7718c29d9616bbd0314d045e.zip
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.
-rw-r--r--src/lib/cdap_req.c25
-rw-r--r--src/lib/cdap_req.h3
2 files changed, 18 insertions, 10 deletions
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);
}
diff --git a/src/lib/cdap_req.h b/src/lib/cdap_req.h
index 9d5cb0c8..b2ded060 100644
--- a/src/lib/cdap_req.h
+++ b/src/lib/cdap_req.h
@@ -31,7 +31,8 @@
#include <pthread.h>
enum creq_state {
- REQ_INIT = 0,
+ REQ_NULL = 0,
+ REQ_INIT,
REQ_PENDING,
REQ_RESPONSE,
REQ_DONE,