]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
fix fifo race in use count dec
authorAnthony Minessale <anthm@freeswitch.org>
Sat, 30 Oct 2010 01:38:59 +0000 (20:38 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Sat, 30 Oct 2010 01:39:07 +0000 (20:39 -0500)
src/include/switch_core_event_hook.h
src/include/switch_module_interfaces.h
src/mod/applications/mod_fifo/mod_fifo.c
src/switch_core_event_hook.c
src/switch_core_state_machine.c

index b60246cf2438f607b23490f5f283198a1d9e7c43..575786f5cec19aa94a6753cf087c1a4f680ad633 100644 (file)
@@ -45,6 +45,7 @@ typedef struct switch_io_event_hook_kill_channel switch_io_event_hook_kill_chann
 typedef struct switch_io_event_hook_send_dtmf switch_io_event_hook_send_dtmf_t;
 typedef struct switch_io_event_hook_recv_dtmf switch_io_event_hook_recv_dtmf_t;
 typedef struct switch_io_event_hook_state_change switch_io_event_hook_state_change_t;
+typedef struct switch_io_event_hook_state_run switch_io_event_hook_state_run_t;
 typedef struct switch_io_event_hook_resurrect_session switch_io_event_hook_resurrect_session_t;
 typedef switch_status_t (*switch_outgoing_channel_hook_t)
                 (switch_core_session_t *, switch_event_t *, switch_caller_profile_t *, switch_core_session_t *, switch_originate_flag_t);
@@ -58,6 +59,7 @@ typedef switch_status_t (*switch_kill_channel_hook_t) (switch_core_session_t *,
 typedef switch_status_t (*switch_send_dtmf_hook_t) (switch_core_session_t *, const switch_dtmf_t *, switch_dtmf_direction_t direction);
 typedef switch_status_t (*switch_recv_dtmf_hook_t) (switch_core_session_t *, const switch_dtmf_t *, switch_dtmf_direction_t direction);
 typedef switch_status_t (*switch_state_change_hook_t) (switch_core_session_t *);
+typedef switch_status_t (*switch_state_run_hook_t) (switch_core_session_t *);
 typedef switch_call_cause_t (*switch_resurrect_session_hook_t) (switch_core_session_t **, switch_memory_pool_t **, void *);
 
 /*! \brief Node in which to store custom receive message callback hooks */
@@ -136,6 +138,13 @@ struct switch_io_event_hook_state_change {
        struct switch_io_event_hook_state_change *next;
 };
 
+/*! \brief Node in which to store state run callback hooks */
+struct switch_io_event_hook_state_run {
+       /*! the state run channel callback hook */
+       switch_state_run_hook_t state_run;
+       struct switch_io_event_hook_state_run *next;
+};
+
 
 struct switch_io_event_hook_resurrect_session {
        switch_resurrect_session_hook_t resurrect_session;
@@ -166,6 +175,7 @@ struct switch_io_event_hooks {
        switch_io_event_hook_recv_dtmf_t *recv_dtmf;
        /*! a list of state change hooks */
        switch_io_event_hook_state_change_t *state_change;
+       switch_io_event_hook_state_run_t *state_run;
        switch_io_event_hook_resurrect_session_t *resurrect_session;
 };
 
@@ -218,6 +228,7 @@ NEW_HOOK_DECL_ADD_P(outgoing_channel);
 NEW_HOOK_DECL_ADD_P(receive_message);
 NEW_HOOK_DECL_ADD_P(receive_event);
 NEW_HOOK_DECL_ADD_P(state_change);
+NEW_HOOK_DECL_ADD_P(state_run);
 NEW_HOOK_DECL_ADD_P(read_frame);
 NEW_HOOK_DECL_ADD_P(write_frame);
 NEW_HOOK_DECL_ADD_P(video_read_frame);
@@ -231,6 +242,7 @@ NEW_HOOK_DECL_REM_P(outgoing_channel);
 NEW_HOOK_DECL_REM_P(receive_message);
 NEW_HOOK_DECL_REM_P(receive_event);
 NEW_HOOK_DECL_REM_P(state_change);
+NEW_HOOK_DECL_REM_P(state_run);
 NEW_HOOK_DECL_REM_P(read_frame);
 NEW_HOOK_DECL_REM_P(write_frame);
 NEW_HOOK_DECL_REM_P(video_read_frame);
index a6013a9386068e9139d3954fca9def63f63ad94a..ae0ce900a9077bdf12d3f5ba872dd56783532ce8 100644 (file)
@@ -134,6 +134,7 @@ typedef switch_status_t (*switch_io_send_dtmf_t) (switch_core_session_t *, const
 typedef switch_status_t (*switch_io_receive_message_t) (switch_core_session_t *, switch_core_session_message_t *);
 typedef switch_status_t (*switch_io_receive_event_t) (switch_core_session_t *, switch_event_t *);
 typedef switch_status_t (*switch_io_state_change_t) (switch_core_session_t *);
+typedef switch_status_t (*switch_io_state_run_t) (switch_core_session_t *);
 typedef switch_status_t (*switch_io_read_video_frame_t) (switch_core_session_t *, switch_frame_t **, switch_io_flag_t, int);
 typedef switch_status_t (*switch_io_write_video_frame_t) (switch_core_session_t *, switch_frame_t *, switch_io_flag_t, int);
 typedef switch_call_cause_t (*switch_io_resurrect_session_t) (switch_core_session_t **, switch_memory_pool_t **, void *);
@@ -174,6 +175,8 @@ struct switch_io_routines {
        switch_io_read_video_frame_t read_video_frame;
        /*! write a video frame to a session */
        switch_io_write_video_frame_t write_video_frame;
+       /*! change a sessions channel run state */
+       switch_io_state_run_t state_run;
        /*! resurrect a session */
        switch_io_resurrect_session_t resurrect_session;
        void *padding[10];
index 4a3cfd595431b61bccd8388bdd2aaab5bfa6692e..520e0628d4cea91c57ae6b1c2c7ea6735fe769ef 100644 (file)
@@ -61,7 +61,8 @@ typedef struct {
 
 typedef enum {
        FIFO_APP_BRIDGE_TAG = (1 << 0),
-       FIFO_APP_TRACKING = (1 << 1)
+       FIFO_APP_TRACKING = (1 << 1),
+       FIFO_APP_DID_HOOK = (1 << 2)
 } fifo_app_flag_t;
 
 
@@ -2019,9 +2020,10 @@ static switch_status_t hanguphook(switch_core_session_t *session)
     switch_channel_t *channel = switch_core_session_get_channel(session);
     switch_channel_state_t state = switch_channel_get_state(channel);
        
-       if (state == CS_HANGUP) {
+       if (state >= CS_HANGUP && !switch_channel_test_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_DID_HOOK)) {
                dec_use_count(session, SWITCH_TRUE);
                switch_core_event_hook_remove_state_change(session, hanguphook);
+               switch_channel_set_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_DID_HOOK);
        }
 
        return SWITCH_STATUS_SUCCESS;
@@ -2044,6 +2046,8 @@ SWITCH_STANDARD_APP(fifo_track_call_function)
                return;
        }
 
+       switch_core_event_hook_add_receive_message(session, messagehook);
+       switch_core_event_hook_add_state_run(session, hanguphook);
 
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s tracking call on uuid %s!\n", switch_channel_get_name(channel), data);
 
@@ -2085,9 +2089,6 @@ SWITCH_STANDARD_APP(fifo_track_call_function)
                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Number", cid_number);
                switch_event_fire(&event);
        }
-       
-       switch_core_event_hook_add_receive_message(session, messagehook);
-       switch_core_event_hook_add_state_change(session, hanguphook);
 }
 
 
@@ -2493,6 +2494,7 @@ SWITCH_STANDARD_APP(fifo_function)
                if (switch_core_event_hook_remove_receive_message(session, messagehook) == SWITCH_STATUS_SUCCESS) {
                        dec_use_count(session, SWITCH_FALSE);
                        switch_core_event_hook_remove_state_change(session, hanguphook);
+                       switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_TRACKING);
                }
 
                if (!zstr(strat_str)) {
index 63420f6f4fe95b67f7e49a4b4a8f02fcc17c343a..102ea20776536c330deefd5ec6d2c698569a6f89 100644 (file)
@@ -35,6 +35,7 @@ NEW_HOOK_DECL(outgoing_channel)
        NEW_HOOK_DECL(receive_message)
        NEW_HOOK_DECL(receive_event)
        NEW_HOOK_DECL(state_change)
+       NEW_HOOK_DECL(state_run)
        NEW_HOOK_DECL(read_frame)
        NEW_HOOK_DECL(write_frame)
        NEW_HOOK_DECL(video_read_frame)
index 27579c2fb4857cdb65e3309067cf765b8e49a58f..439f9b7d8961d8f334c058d1c1c98ba55df1d09b 100644 (file)
@@ -314,11 +314,25 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
                        int proceed = 1;
                        int global_proceed = 1;
                        int do_extra_handlers = 1;
+                       switch_io_event_hook_state_run_t *ptr;
+                       switch_status_t rstatus = SWITCH_STATUS_SUCCESS;
 
                        switch_channel_set_running_state(session->channel, state);
                        switch_channel_clear_flag(session->channel, CF_TRANSFER);
                        switch_channel_clear_flag(session->channel, CF_REDIRECT);
-
+                       
+                       if (session->endpoint_interface->io_routines->state_run) {
+                               rstatus = session->endpoint_interface->io_routines->state_run(session);
+                       }
+                       
+                       if (rstatus == SWITCH_STATUS_SUCCESS) {
+                               for (ptr = session->event_hooks.state_run; ptr; ptr = ptr->next) {
+                                       if ((rstatus = ptr->state_run(session)) != SWITCH_STATUS_SUCCESS) {
+                                               break;
+                                       }
+                               }
+                       }
+                       
                        switch (state) {
                        case CS_NEW:            /* Just created, Waiting for first instructions */
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) State NEW\n", switch_channel_get_name(session->channel));