summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri.staessens@ugent.be>2017-08-05 10:05:44 -0600
committerDimitri Staessens <dimitri.staessens@ugent.be>2017-08-05 10:05:44 -0600
commit57784d85969a0bcf8599442e3be5ae7edf1fbe10 (patch)
tree0c519efe6d6e9b4c8128c0522d81b9e981af3629
parentffd8de94c9b3829116f6604dfae8aa9a24ef2ef3 (diff)
downloadouroboros-57784d85969a0bcf8599442e3be5ae7edf1fbe10.tar.gz
ouroboros-57784d85969a0bcf8599442e3be5ae7edf1fbe10.zip
irmd: Don't call ipcp_flow_dealloc under lock
When a process was killed, ipcp_flow_dealloc was called under a lock, causing a deadlock in the IRMd because handling the IPCP response also needs to take the same lock (the IPCP calls flow_dealloc to finalize this). This deadlock also resulted in the IPCP always reporting that it failed to send a reply message as the deadlock effectively blocks the IRMd until its socket timeout expired and thus the IPCP was always responding to an already closed socket.
-rw-r--r--src/irmd/main.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/src/irmd/main.c b/src/irmd/main.c
index 96b0b729..a8ccccb2 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -1638,6 +1638,8 @@ void * irm_sanitize(void * o)
pthread_rwlock_wrlock(&irmd.flows_lock);
list_for_each_safe(p, h, &irmd.irm_flows) {
+ int ipcpi;
+ int port_id;
struct irm_flow * f =
list_entry(p, struct irm_flow, next);
@@ -1645,9 +1647,13 @@ void * irm_sanitize(void * o)
&& ts_diff_ms(&f->t0, &now) > IRMD_FLOW_TIMEOUT) {
log_dbg("Pending port_id %d timed out.",
f->port_id);
- f->n_1_api = -1;
+ f->n_api = -1;
irm_flow_set_state(f, FLOW_DEALLOC_PENDING);
- ipcp_flow_dealloc(f->n_1_api, f->port_id);
+ ipcpi = f->n_1_api;
+ port_id = f->port_id;
+ pthread_rwlock_unlock(&irmd.flows_lock);
+ ipcp_flow_dealloc(ipcpi, port_id);
+ pthread_rwlock_wrlock(&irmd.flows_lock);
continue;
}
@@ -1660,7 +1666,11 @@ void * irm_sanitize(void * o)
shm_flow_set_destroy(set);
f->n_api = -1;
irm_flow_set_state(f, FLOW_DEALLOC_PENDING);
- ipcp_flow_dealloc(f->n_1_api, f->port_id);
+ ipcpi = f->n_1_api;
+ port_id = f->port_id;
+ pthread_rwlock_unlock(&irmd.flows_lock);
+ ipcp_flow_dealloc(ipcpi, port_id);
+ pthread_rwlock_wrlock(&irmd.flows_lock);
continue;
}