summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordimitri staessens <dimitri.staessens@ugent.be>2017-08-04 11:47:41 +0200
committerdimitri staessens <dimitri.staessens@ugent.be>2017-08-04 12:24:41 +0200
commit055835e5b06d7f18d94ca1d6b2df5f0a3ec3e954 (patch)
treede667f46d84fbefea971d07f6a0b4f9be05f2cf3 /src
parent9017e3006c1e1246de5291f13319a763fd440e2f (diff)
downloadouroboros-055835e5b06d7f18d94ca1d6b2df5f0a3ec3e954.tar.gz
ouroboros-055835e5b06d7f18d94ca1d6b2df5f0a3ec3e954.zip
irmd: Release lock before ipcp_query
The blocking ipcp_query call was called under reg_lock, causing flow_allocs over the shim-eth-llc to block the irmd for prolonged timespans.
Diffstat (limited to 'src')
-rw-r--r--src/irmd/main.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/src/irmd/main.c b/src/irmd/main.c
index 63ae6b13..912234d6 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -232,10 +232,14 @@ static struct ipcp_entry * get_ipcp_entry_by_name(const char * name)
static struct ipcp_entry * get_ipcp_by_dst_name(const char * name)
{
- struct list_head * p = NULL;
- uint8_t * hash;
+ struct list_head * p;
+ struct list_head * h;
+ uint8_t * hash;
+ pid_t api;
- list_for_each(p, &irmd.ipcps) {
+ pthread_rwlock_rdlock(&irmd.reg_lock);
+
+ list_for_each_safe(p, h, &irmd.ipcps) {
struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next);
if (e->dif_name == NULL)
continue;
@@ -246,14 +250,22 @@ static struct ipcp_entry * get_ipcp_by_dst_name(const char * name)
str_hash(e->dir_hash_algo, hash, name);
- if (ipcp_query(e->api, hash, IPCP_HASH_LEN(e)) == 0) {
+ api = e->api;
+
+ pthread_rwlock_unlock(&irmd.reg_lock);
+
+ if (ipcp_query(api, hash, IPCP_HASH_LEN(e)) == 0) {
free(hash);
return e;
}
free(hash);
+
+ pthread_rwlock_rdlock(&irmd.reg_lock);
}
+ pthread_rwlock_unlock(&irmd.reg_lock);
+
return NULL;
}
@@ -1099,16 +1111,12 @@ static int flow_alloc(pid_t api,
int state;
uint8_t * hash;
- pthread_rwlock_rdlock(&irmd.reg_lock);
-
ipcp = get_ipcp_by_dst_name(dst);
if (ipcp == NULL) {
- pthread_rwlock_unlock(&irmd.reg_lock);
log_info("Destination %s unreachable.", dst);
return -1;
}
- pthread_rwlock_unlock(&irmd.reg_lock);
pthread_rwlock_wrlock(&irmd.flows_lock);
port_id = bmp_allocate(irmd.port_ids);
if (!bmp_is_id_valid(irmd.port_ids, port_id)) {