From 9301dcbc95c95a82eba9e831f49253dcad73abb2 Mon Sep 17 00:00:00 2001 From: dimitri staessens Date: Sat, 4 Feb 2017 20:05:20 +0100 Subject: lib: Handle receiving CDAP reply before wait In extreme cases, the response to a CDAP request can arrive before the AE doing the request has called cdap_request_wait. This PR handles it by waiting for the state to move away from INIT before responding. --- src/lib/cdap_req.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/lib/cdap_req.c b/src/lib/cdap_req.c index 565cafd0..2f55b107 100644 --- a/src/lib/cdap_req.c +++ b/src/lib/cdap_req.c @@ -108,6 +108,7 @@ int cdap_req_wait(struct cdap_req * creq) } creq->state = REQ_PENDING; + pthread_cond_broadcast(&creq->cond); while (creq->state == REQ_PENDING) { ret = -pthread_cond_timedwait(&creq->cond, @@ -131,13 +132,20 @@ int cdap_req_wait(struct cdap_req * creq) return ret; } -void cdap_req_respond(struct cdap_req * creq, int response, buffer_t data) +void cdap_req_respond(struct cdap_req * creq, + int response, + buffer_t data) { assert(creq); pthread_mutex_lock(&creq->lock); + while (creq->state == REQ_INIT) + pthread_cond_wait(&creq->cond, &creq->lock); + if (creq->state != REQ_PENDING) { + creq->state = REQ_NULL; + pthread_cond_broadcast(&creq->cond); pthread_mutex_unlock(&creq->lock); return; } -- cgit v1.2.3 From 49fb847ff3dc8b7de91eb3a54524e60b145f9bf4 Mon Sep 17 00:00:00 2001 From: dimitri staessens Date: Sat, 4 Feb 2017 20:08:02 +0100 Subject: irmd: Handle death of IPCP gracefully If an IPCP SEGVs abruptly, the sanitizer in the IRMd would also cause a SEGV because of looping over a registry linked list inside another safe loop over the same list. A function is added to the registry to avoid this. --- src/irmd/main.c | 5 +++-- src/irmd/registry.c | 34 ++++++++++++++++++++++++---------- src/irmd/registry.h | 3 +++ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/irmd/main.c b/src/irmd/main.c index 02ffb21b..98e79aa8 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -985,9 +985,9 @@ static struct irm_flow * flow_accept(pid_t api, char ** dst_ae_name, e = api_table_get(&irmd->api_table, api); if (e == NULL) { - LOG_DBG("Process gone while accepting flow."); pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); + LOG_DBG("Process gone while accepting flow."); return NULL; } @@ -1000,6 +1000,7 @@ static struct irm_flow * flow_accept(pid_t api, char ** dst_ae_name, if (reg_entry_get_state(re) != REG_NAME_FLOW_ARRIVED) { pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); + LOG_ERR("Entry in wrong state."); return NULL; } pthread_rwlock_unlock(&irmd->reg_lock); @@ -1671,7 +1672,7 @@ void * irm_sanitize(void * o) continue; LOG_DBG("Dead AP-I removed from: %d %s.", a->pid, e->name); - reg_entry_del_api(e, a->pid); + reg_entry_del_pid_el(e, a); } } diff --git a/src/irmd/registry.c b/src/irmd/registry.c index 7e21375e..fec69cfa 100644 --- a/src/irmd/registry.c +++ b/src/irmd/registry.c @@ -296,6 +296,29 @@ int reg_entry_add_api(struct reg_entry * e, pid_t api) return 0; } +static void reg_entry_check_state(struct reg_entry * e) +{ + if (list_is_empty(&e->reg_apis)) { + if (!list_is_empty(&e->reg_apns)) + e->state = REG_NAME_AUTO_ACCEPT; + else + e->state = REG_NAME_IDLE; + } else { + e->state = REG_NAME_FLOW_ACCEPT; + } + + pthread_cond_broadcast(&e->state_cond); +} + +void reg_entry_del_pid_el(struct reg_entry * e, + struct pid_el * p) +{ + list_del(&p->next); + free(p); + + reg_entry_check_state(e); +} + void reg_entry_del_api(struct reg_entry * e, pid_t api) { struct list_head * p; @@ -312,16 +335,7 @@ void reg_entry_del_api(struct reg_entry * e, pid_t api) } } - if (list_is_empty(&e->reg_apis)) { - if (!list_is_empty(&e->reg_apns)) - e->state = REG_NAME_AUTO_ACCEPT; - else - e->state = REG_NAME_IDLE; - } else { - e->state = REG_NAME_FLOW_ACCEPT; - } - - pthread_cond_broadcast(&e->state_cond); + reg_entry_check_state(e); } pid_t reg_entry_get_api(struct reg_entry * e) diff --git a/src/irmd/registry.h b/src/irmd/registry.h index bdd5cad0..7713e278 100644 --- a/src/irmd/registry.h +++ b/src/irmd/registry.h @@ -84,6 +84,9 @@ int reg_entry_add_api(struct reg_entry * e, void reg_entry_del_api(struct reg_entry * e, pid_t api); +void reg_entry_del_pid_el(struct reg_entry * e, + struct pid_el * a); + pid_t reg_entry_get_api(struct reg_entry * e); enum reg_name_state reg_entry_get_state(struct reg_entry * e); -- cgit v1.2.3