]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
fix obscure race condition
authorAnthony Minessale <anthony.minessale@gmail.com>
Mon, 21 Jan 2008 17:14:43 +0000 (17:14 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Mon, 21 Jan 2008 17:14:43 +0000 (17:14 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@7311 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/private/switch_core_pvt.h
src/include/switch_types.h
src/mod/endpoints/mod_sofia/mod_sofia.c
src/switch_core_media_bug.c
src/switch_core_session.c
src/switch_ivr_async.c

index d50f8962061690b9cd68f3c4be0655bec1289ac1..11c7a8c80a9c701b929af4273f163a7fa7c9dbd9 100644 (file)
@@ -153,6 +153,7 @@ struct switch_media_bug {
        uint32_t flags;
        uint8_t ready;
        time_t stop_time;
+       switch_thread_id_t thread_id;
        struct switch_media_bug *next;
 };
 
index 4fe49cc6c53e4a39f2fd53e4debae9389c805351..ed7c81406291b3620c53e2ac4435767a92d8cbd6 100644 (file)
@@ -830,6 +830,7 @@ SMBF_WRITE_REPLACE - Replace the Write Stream
 SMBF_READ_REPLACE - Replace the Read Stream
 SMBF_STEREO - Record in stereo
 SMBF_ANSWER_RECORD_REQ - Don't record until the channel is answered
+SMBF_THREAD_LOCK - Only let the same thread who created the bug remove it.
 </pre>
 */
 typedef enum {
@@ -840,7 +841,8 @@ typedef enum {
        SMBF_READ_REPLACE = (1 << 3),
        SMBF_READ_PING = (1 << 4),
        SMBF_STEREO = (1 << 5),
-       SMBF_RECORD_ANSWER_REQ = (1 << 6)
+       SMBF_RECORD_ANSWER_REQ = (1 << 6),
+       SMBF_THREAD_LOCK = (1 << 7)
 } switch_media_bug_flag_t;
 
 /*!
index 16be182bb43746a819b1cc277b803035239c8918..34cab0e514876831cb2ce87d322adfda839f42e9 100644 (file)
@@ -1748,11 +1748,11 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session
                } else if (!strchr(dest, '@')) {
                        char buf[128];
                        tech_pvt->e_dest = switch_core_session_strdup(nsession, dest);
-                       if (sofia_reg_find_reg_url(profile, dest, profile_name, buf, sizeof(buf))) {
+                       if (sofia_reg_find_reg_url(profile, dest, profile->name, buf, sizeof(buf))) {
                                tech_pvt->dest = switch_core_session_strdup(nsession, buf);
-                               tech_pvt->local_url = switch_core_session_sprintf(nsession, "%s@%s", dest, profile_name);
+                               tech_pvt->local_url = switch_core_session_sprintf(nsession, "%s@%s", dest, profile->name);
                        } else {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate registered user %s@%s\n", dest, profile_name);
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate registered user %s@%s\n", dest, profile->name);
                                cause = SWITCH_CAUSE_NO_ROUTE_DESTINATION;
                                goto error;
                        }
index 47b4ed6300f71281945a19be4c67a9cc77272aed..07307a33146b3defb7d02d46ccb1e36074b4985d 100644 (file)
@@ -244,6 +244,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_add(switch_core_session_t
                switch_buffer_create_dynamic(&bug->raw_write_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, MAX_BUG_BUFFER);
                switch_mutex_init(&bug->write_mutex, SWITCH_MUTEX_NESTED, session->pool);
        }
+
+       if ((bug->flags & SMBF_THREAD_LOCK)) {
+               bug->thread_id = switch_thread_self();
+       }
+
+
        bug->ready = 1;
        switch_thread_rwlock_wrlock(session->bug_rwlock);
        bug->next = session->bugs;
@@ -269,6 +275,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove_all(switch_core_ses
        if (session->bugs) {
                switch_thread_rwlock_wrlock(session->bug_rwlock);
                for (bp = session->bugs; bp; bp = bp->next) {
+                       if (bp->thread_id && bp->thread_id != switch_thread_self()) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "BUG is thread locked skipping.\n");
+                               continue;
+                       }
+
                        if (bp->callback) {
                                bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_CLOSE);
                        }
@@ -287,6 +298,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_close(switch_media_bug_t *
 {
        switch_media_bug_t *bp = *bug;
        if (bp) {
+               if (bp->thread_id && bp->thread_id != switch_thread_self()) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "BUG is thread locked skipping.\n");
+                       return SWITCH_STATUS_FALSE;
+               }
+
                if (bp->callback) {
                        bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_CLOSE);
                        bp->ready = 0;
@@ -308,6 +324,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_remove(switch_core_session
        if (session->bugs) {
                switch_thread_rwlock_wrlock(session->bug_rwlock);
                for (bp = session->bugs; bp; bp = bp->next) {
+                       if (bp->thread_id && bp->thread_id != switch_thread_self()) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "BUG is thread locked skipping.\n");
+                               continue;
+                       }
+
                        if (!bp->ready) {
                                continue;
                        }
index a7d4a9aa193e56db2cc8edc2ea6c94780192b901..ff779042ba7f12d0d8b770368123c5d89d442f8e 100644 (file)
@@ -657,7 +657,8 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t *
        switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_NOTICE, "Close Channel %s [%s]\n", 
                                          switch_channel_get_name((*session)->channel),
                                          switch_channel_state_name(switch_channel_get_state((*session)->channel)));
-       
+
+       switch_core_media_bug_remove_all(*session);     
        switch_ivr_deactivate_unicast(*session);
        
        switch_scheduler_del_task_group((*session)->uuid_str);
@@ -674,7 +675,7 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t *
                switch_event_fire(&event);
        }
 
-       switch_core_media_bug_remove_all(*session);
+
        switch_buffer_destroy(&(*session)->raw_read_buffer);
        switch_buffer_destroy(&(*session)->raw_write_buffer);
        switch_ivr_clear_speech_cache(*session);
@@ -694,10 +695,7 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t * thr
        switch_core_session_t *session = obj;
        session->thread = thread;
 
-
-
        switch_core_session_run(session);
-       switch_core_media_bug_remove_all(session);
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session %"SWITCH_SIZE_T_FMT" (%s) Locked, Waiting on external entities\n",
                                          session->id, switch_channel_get_name(session->channel));
        switch_core_session_write_lock(session);
index 6aebd8918fccda388743c6c05455cd645f69118e..6dd3bd774f36c208105bf65191a4da10647e78d5 100644 (file)
@@ -503,9 +503,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
                switch_channel_t *tchannel = switch_core_session_get_channel(tsession);
                switch_frame_t *read_frame, write_frame = { 0 };
                switch_codec_t codec = {0};
-               int16_t buf[1024];
+               int16_t buf[8192];
                switch_codec_t *tread_codec = switch_core_session_get_read_codec(tsession);
-               
+               int tlen = tread_codec->implementation->bytes_per_frame;
+
                ep = switch_core_session_alloc(session, sizeof(*ep));
 
                switch_channel_pre_answer(channel);
@@ -543,7 +544,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
 
                
                if (switch_core_media_bug_add(tsession, eavesdrop_callback, ep, 0, 
-                                                                         SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_REPLACE | SMBF_WRITE_REPLACE | SMBF_READ_PING,
+                                                                         SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_REPLACE | SMBF_WRITE_REPLACE | SMBF_READ_PING | SMBF_THREAD_LOCK,
                                                                          &bug) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot attach bug\n");
                        goto end;
@@ -630,11 +631,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_eavesdrop_session(switch_core_session
                                switch_buffer_unlock(ep->w_buffer);
                        }
 
-
-                       if (len > tread_codec->implementation->bytes_per_frame) {
-                               len = tread_codec->implementation->bytes_per_frame;
+                       if (len > tlen) {
+                               len = tlen;
                        }
-                       
+
             if (switch_buffer_inuse(ep->buffer) >= len) {
                 switch_buffer_lock(ep->buffer);                                
                                while (switch_buffer_inuse(ep->buffer) >= len) {