diff options
Diffstat (limited to 'src/ipcpd/local/main.c')
-rw-r--r-- | src/ipcpd/local/main.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/src/ipcpd/local/main.c b/src/ipcpd/local/main.c index da84e517..160e07e0 100644 --- a/src/ipcpd/local/main.c +++ b/src/ipcpd/local/main.c @@ -221,17 +221,17 @@ static int local_ipcp_flow_alloc_resp(int fd, int response, const buffer_t * data) { - int out_fd; - time_t mpl = IPCP_LOCAL_MPL; + struct timespec wait = TIMESPEC_INIT_MS(1); + time_t mpl = IPCP_LOCAL_MPL; + int out_fd; if (ipcp_wait_flow_resp(fd) < 0) { log_err("Failed waiting for IRMd response."); return -1; } - pthread_rwlock_wrlock(&local_data.lock); - if (response < 0) { + pthread_rwlock_wrlock(&local_data.lock); if (local_data.in_out[fd] != -1) local_data.in_out[local_data.in_out[fd]] = fd; local_data.in_out[fd] = -1; @@ -239,15 +239,24 @@ static int local_ipcp_flow_alloc_resp(int fd, return 0; } + pthread_rwlock_rdlock(&local_data.lock); + out_fd = local_data.in_out[fd]; if (out_fd == -1) { pthread_rwlock_unlock(&local_data.lock); - log_err("Invalid out_fd."); - return -1; + log_dbg("Potential race detected"); + nanosleep(&wait, NULL); + pthread_rwlock_rdlock(&local_data.lock); + out_fd = local_data.in_out[fd]; } pthread_rwlock_unlock(&local_data.lock); + if (out_fd == -1) { + log_err("Invalid out_fd."); + return -1; + } + fset_add(local_data.flows, fd); if (ipcp_flow_alloc_reply(out_fd, response, mpl, data) < 0) { |