diff --git a/src/mod/event_handlers/mod_erlang_event/ei_helpers.c b/src/mod/event_handlers/mod_erlang_event/ei_helpers.c index 9700753603..4f314c9733 100644 --- a/src/mod/event_handlers/mod_erlang_event/ei_helpers.c +++ b/src/mod/event_handlers/mod_erlang_event/ei_helpers.c @@ -258,6 +258,19 @@ void ei_hash_ref(erlang_ref *ref, char *output) } +int ei_compare_pids(erlang_pid *pid1, erlang_pid *pid2) +{ + if ((!strcmp(pid1->node, pid2->node)) && + pid1->creation == pid2->creation && + pid1->num == pid2->num && + pid1->serial == pid2->serial) { + return 0; + } else { + return 1; + } +} + + switch_status_t initialise_ei(struct ei_cnode_s *ec) { switch_status_t rv; diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index 507f7fcfee..268787bcf7 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -114,7 +114,7 @@ static void remove_binding(listener_t *listener, erlang_pid *pid) { for (ptr = bindings.head; ptr; lst = ptr, ptr = ptr->next) { if ((listener && ptr->listener == listener) || - (pid && (&ptr->process.type == ERLANG_PID) && (!strcmp(pid->node, ptr->process.pid.node)) && pid->creation == ptr->process.pid.creation && pid->num == ptr->process.pid.num && pid->serial == ptr->process.pid.serial)) { + (pid && (ptr->process.type == ERLANG_PID) && !ei_compare_pids(&ptr->process.pid, pid))) { if (bindings.head == ptr) { if (ptr->next) { bindings.head = ptr->next; @@ -301,6 +301,49 @@ static void add_session_elem_to_listener(listener_t *listener, session_elem_t *s switch_mutex_unlock(listener->session_mutex); } +static void remove_session_elem_from_listener(listener_t *listener, session_elem_t *session) +{ + session_elem_t *s, *last = NULL; + + if(!session) + return; + + switch_mutex_lock(listener->session_mutex); + for(s = listener->session_list; s; s = s->next) { + if (s == session) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removing session\n"); + if (last) { + last->next = s->next; + } else { + listener->session_list = s->next; + } + switch_channel_clear_flag(switch_core_session_get_channel(s->session), CF_CONTROLLED); + /* this allows the application threads to exit */ + switch_clear_flag_locked(s, LFLAG_SESSION_ALIVE); + switch_core_session_rwunlock(s->session); + } + last = s; + } + switch_mutex_unlock(listener->session_mutex); +} + + +session_elem_t * find_session_elem_by_pid(listener_t *listener, erlang_pid *pid) +{ + session_elem_t *s = NULL; + + switch_mutex_lock(listener->session_mutex); + for (s = listener->session_list; s; s = s->next) { + if (s->process.type == ERLANG_PID && ei_compare_pids(pid, &s->process.pid)) { + break; + } + } + switch_mutex_unlock(listener->session_mutex); + + return s; +} + + static switch_xml_t erlang_fetch(const char *sectionstr, const char *tag_name, const char *key_name, const char *key_value, switch_event_t *params, void *user_data) { @@ -635,6 +678,8 @@ static void listener_main_loop(listener_t *listener) case ERL_EXIT : switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "erl_exit from %s <%d.%d.%d>\n", msg.from.node, msg.from.creation, msg.from.num, msg.from.serial); remove_binding(NULL, &msg.from); + /* TODO - if a spawned process that was handling an outbound call fails.. what do we do with the call? */ + remove_session_elem_from_listener(listener, find_session_elem_by_pid(listener, &msg.from)); /* TODO - check if this linked pid is any of the log/event handler processes and cleanup if it is. */ break; default : @@ -955,6 +1000,8 @@ session_elem_t* attach_call_to_spawned_process(listener_t* listener, char *modul switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "got pid!\n"); + ei_link(listener, pid, ei_self(listener->ec)); + session_element->process.type = ERLANG_PID; memcpy(&session_element->process.pid, pid, sizeof(erlang_pid)); switch_set_flag(session_element, LFLAG_SESSION_ALIVE); diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h index 0549efb385..4dbaf1ecf1 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h @@ -54,7 +54,6 @@ struct session_elem { switch_core_session_t *session; switch_mutex_t *flag_mutex; uint32_t flags; - /* registered process name that will receive call notifications from this session */ struct erlang_process process; switch_queue_t *event_queue; struct session_elem *next; @@ -194,6 +193,7 @@ void ei_x_print_reg_msg(ei_x_buff *buf, char *dest, int send); void ei_x_print_msg(ei_x_buff *buf, erlang_pid *pid, int send); int ei_sendto(ei_cnode *ec, int fd, struct erlang_process *process, ei_x_buff *buf); void ei_hash_ref(erlang_ref *ref, char *output); +int ei_compare_pids(erlang_pid *pid1, erlang_pid *pid2); switch_status_t initialise_ei(struct ei_cnode_s *ec); #define ei_encode_switch_event(_b, _e) ei_encode_switch_event_tag(_b, _e, "event")