diff options
author | dimitri staessens <[email protected]> | 2017-04-06 16:46:52 +0200 |
---|---|---|
committer | dimitri staessens <[email protected]> | 2017-04-06 16:51:02 +0200 |
commit | a4ce5e7d47d27c8b582e27b38ce61c9cb9735992 (patch) | |
tree | ec99dad12704ff9728d408fb93b356d449fe70c8 /src/ipcpd/normal/fmgr.c | |
parent | 0f9954dd086834a996d5585d923364b765b752e4 (diff) | |
download | ouroboros-a4ce5e7d47d27c8b582e27b38ce61c9cb9735992.tar.gz ouroboros-a4ce5e7d47d27c8b582e27b38ce61c9cb9735992.zip |
ipcpd: Fix race condition with concurrent allocs
Diffstat (limited to 'src/ipcpd/normal/fmgr.c')
-rw-r--r-- | src/ipcpd/normal/fmgr.c | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/src/ipcpd/normal/fmgr.c b/src/ipcpd/normal/fmgr.c index 3191eac5..19c329af 100644 --- a/src/ipcpd/normal/fmgr.c +++ b/src/ipcpd/normal/fmgr.c @@ -542,6 +542,7 @@ static int np1_flow_dealloc(int fd) int fmgr_np1_alloc_resp(int fd, int response) { + struct timespec ts = {0, FD_UPDATE_TIMEOUT * 1000}; flow_alloc_msg_t msg = FLOW_ALLOC_MSG__INIT; buffer_t buf; @@ -549,6 +550,23 @@ int fmgr_np1_alloc_resp(int fd, msg.response = response; msg.has_response = true; + pthread_mutex_lock(&ipcpi.alloc_lock); + + while (ipcpi.alloc_id != fd && ipcp_get_state() == IPCP_OPERATIONAL) + pthread_cond_timedwait(&ipcpi.alloc_cond, + &ipcpi.alloc_lock, + &ts); + + if (ipcp_get_state() != IPCP_OPERATIONAL) { + pthread_mutex_unlock(&ipcpi.alloc_lock); + return -1; + } + + ipcpi.alloc_id = -1; + pthread_cond_broadcast(&ipcpi.alloc_cond); + + pthread_mutex_unlock(&ipcpi.alloc_lock); + buf.len = flow_alloc_msg__get_packed_size(&msg); if (buf.len == 0) return -1; @@ -601,10 +619,11 @@ int fmgr_np1_dealloc(int fd) int fmgr_np1_post_buf(cep_id_t cep_id, buffer_t * buf) { - int ret = 0; - int fd; + struct timespec ts = {0, FD_UPDATE_TIMEOUT * 1000}; + int ret = 0; + int fd; flow_alloc_msg_t * msg; - qoscube_t cube; + qoscube_t cube; /* Depending on the message call the function in ipcp-dev.h */ @@ -617,6 +636,21 @@ int fmgr_np1_post_buf(cep_id_t cep_id, switch (msg->code) { case FLOW_ALLOC_CODE__FLOW_REQ: pthread_mutex_lock(&ipcpi.alloc_lock); + + while (ipcpi.alloc_id != -1 && + ipcp_get_state() == IPCP_OPERATIONAL) + pthread_cond_timedwait(&ipcpi.alloc_cond, + &ipcpi.alloc_lock, + &ts); + + if (ipcp_get_state() != IPCP_OPERATIONAL) { + log_dbg("Won't allocate over non-operational IPCP."); + pthread_mutex_unlock(&ipcpi.alloc_lock); + return -1; + } + + assert(ipcpi.alloc_id == -1); + fd = ipcp_flow_req_arr(getpid(), msg->dst_name, msg->qoscube); @@ -633,6 +667,10 @@ int fmgr_np1_post_buf(cep_id_t cep_id, fmgr.np1_cep_id_to_fd[cep_id] = fd; pthread_rwlock_unlock(&fmgr.np1_flows_lock); + + ipcpi.alloc_id = fd; + pthread_cond_broadcast(&ipcpi.alloc_cond); + pthread_mutex_unlock(&ipcpi.alloc_lock); break; |