]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
fix race condition on device state destroy
authorAnthony Minessale <anthm@freeswitch.org>
Fri, 28 Jun 2013 19:20:58 +0000 (14:20 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Fri, 28 Jun 2013 19:21:04 +0000 (14:21 -0500)
src/mod/applications/mod_skel/mod_skel.c
src/switch_channel.c

index 4722b77d58ff19490c28567dfde2db8ea3726731..37f155aef69b7ef358ce095ad41acf8bbb725fdb 100644 (file)
@@ -214,6 +214,28 @@ SWITCH_STANDARD_API(skel_function)
        return SWITCH_STATUS_SUCCESS;
 }
 
+static void mycb(switch_core_session_t *session, switch_channel_callstate_t callstate, switch_device_record_t *drec)
+{
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+
+       switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, 
+                                         "%s device: %s\nState: %s Dev State: %s/%s Total:%u Offhook:%u Active:%u Held:%u Hungup:%u Dur: %u %s\n", 
+                                         switch_channel_get_name(channel),
+                                         drec->device_id,
+                                         switch_channel_callstate2str(callstate),
+                                         switch_channel_device_state2str(drec->last_state),
+                                         switch_channel_device_state2str(drec->state),
+                                         drec->stats.total,
+                                         drec->stats.offhook,
+                                         drec->stats.active,
+                                         drec->stats.held,
+                                         drec->stats.hup,
+                                         drec->active_stop ? (uint32_t)(drec->active_stop - drec->active_start) / 1000 : 0,
+                                         switch_channel_test_flag(channel, CF_FINAL_DEVICE_LEG) ? "FINAL LEG" : "");
+
+}
+
+
 /* Macro expands to: switch_status_t mod_skel_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
 SWITCH_MODULE_LOAD_FUNCTION(mod_skel_load)
 {
@@ -227,6 +249,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skel_load)
 
        SWITCH_ADD_API(api_interface, "skel", "Skel API", skel_function, "syntax");
 
+       switch_channel_bind_device_state_handler(mycb, NULL);
+
        /* indicate that the module should continue to be loaded */
        return SWITCH_STATUS_SUCCESS;
 }
@@ -237,6 +261,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skel_load)
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skel_shutdown)
 {
        /* Cleanup dynamically allocated config settings */
+       switch_channel_unbind_device_state_handler(mycb);
        switch_xml_config_cleanup(instructions);
        return SWITCH_STATUS_SUCCESS;
 }
index 429a48d73fb6446c4b1784a78201de9afd825964..da41b92739e13e9d6fe0e595daf00444af012905 100644 (file)
@@ -4701,31 +4701,36 @@ SWITCH_DECLARE(void) switch_channel_clear_device_record(switch_channel_t *channe
 static void process_device_hup(switch_channel_t *channel)
 {
        switch_hold_record_t *hr, *newhr, *last = NULL;
+       switch_device_record_t *drec = NULL;
+       switch_device_node_t *node;
 
        if (!channel->device_node) {
                return;
        }
        
        switch_mutex_lock(globals.device_mutex);
-       channel->device_node->hup_profile = switch_caller_profile_dup(channel->device_node->parent->pool, channel->caller_profile);
-       fetch_device_stats(channel->device_node->parent);
+       node = channel->device_node;
+       drec = channel->device_node->parent;
 
-       switch_ivr_generate_xml_cdr(channel->session, &channel->device_node->xml_cdr);
-       if (switch_event_create(&channel->device_node->event, SWITCH_EVENT_CALL_DETAIL) == SWITCH_STATUS_SUCCESS) {
-               switch_channel_event_set_extended_data(channel, channel->device_node->event);
+       node->hup_profile = switch_caller_profile_dup(drec->pool, channel->caller_profile);
+       fetch_device_stats(drec);
+
+       switch_ivr_generate_xml_cdr(channel->session, &node->xml_cdr);
+       if (switch_event_create(&node->event, SWITCH_EVENT_CALL_DETAIL) == SWITCH_STATUS_SUCCESS) {
+               switch_channel_event_set_extended_data(channel, node->event);
        }
 
        for (hr = channel->hold_record; hr; hr = hr->next) {
-               newhr = switch_core_alloc(channel->device_node->parent->pool, sizeof(*newhr));
+               newhr = switch_core_alloc(drec->pool, sizeof(*newhr));
                newhr->on = hr->on;
                newhr->off = hr->off;
 
                if (hr->uuid) {
-                       newhr->uuid = switch_core_strdup(channel->device_node->parent->pool, hr->uuid);
+                       newhr->uuid = switch_core_strdup(drec->pool, hr->uuid);
                }
 
-               if (!channel->device_node->hold_record) {
-                       channel->device_node->hold_record = newhr;
+               if (!node->hold_record) {
+                       node->hold_record = newhr;
                } else {
                        last->next = newhr;
                }
@@ -4733,15 +4738,17 @@ static void process_device_hup(switch_channel_t *channel)
                last = newhr;
        }       
 
-       if (!channel->device_node->parent->stats.offhook) { /* this is final call */
+       if (!drec->stats.offhook) { /* this is final call */
 
-               switch_core_hash_delete(globals.device_hash, channel->device_node->parent->device_id);
+               switch_core_hash_delete(globals.device_hash, drec->device_id);
                switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Processing last call from device [%s]\n", 
-                                                 channel->device_node->parent->device_id);
+                                                 drec->device_id);
                switch_channel_set_flag(channel, CF_FINAL_DEVICE_LEG);
+       } else {
+               channel->device_node = NULL;
        }
 
-       channel->device_node->parent->refs--;
+       drec->refs--;
 
        switch_mutex_unlock(globals.device_mutex);