]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Monitor spawned outbound processes for premature exits
authorAndrew Thompson <andrew@hijacked.us>
Mon, 26 Jan 2009 04:09:08 +0000 (04:09 +0000)
committerAndrew Thompson <andrew@hijacked.us>
Mon, 26 Jan 2009 04:09:08 +0000 (04:09 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11489 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/event_handlers/mod_erlang_event/ei_helpers.c
src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c
src/mod/event_handlers/mod_erlang_event/mod_erlang_event.h

index 970075360324c9dd00324432ed79192cd73cc927..4f314c9733acad661384a42f14431631d874c68e 100644 (file)
@@ -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;
index 507f7fcfee35aa8804edfe9a49a4bbfaf4de9d92..268787bcf7cba09d1200d2b8bf8534b29661c195 100644 (file)
@@ -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);
index 0549efb385e1a51e9f81f5ae09600a54f9638092..4dbaf1ecf1302543c974783bca4cd2105276fc22 100644 (file)
@@ -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")