]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: * Avoid acquiring the span mutex if the pendingchans queue is available...
authorMoises Silva <moy@sangoma.com>
Mon, 24 Oct 2011 16:43:54 +0000 (12:43 -0400)
committerMoises Silva <moy@sangoma.com>
Mon, 24 Oct 2011 16:43:54 +0000 (12:43 -0400)
         * FreeTDM modules using the old FTDM_SPAN_STATE_CHANGE flag should be updated   *
         * until then, they are still vulnerable to deadlock situations                  *
         * Modules pending update: (ftmod_analog, ftmod_libpri, ftmod_isdn)              *
         * Fixes Sangoma redmine ticket #1791 0 FTDM span stop deadlock                  *

libs/freetdm/src/ftdm_state.c
libs/freetdm/src/include/private/ftdm_types.h

index 54ecde530d2ec3a7fd76135008fff4b36cbbcd9f..d3f99f6074bef9363db46b4a96828dd2d7dc8bb1 100644 (file)
@@ -370,12 +370,19 @@ end:
        }
        ftdm_set_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
 
-       ftdm_mutex_lock(ftdmchan->span->mutex);
-       ftdm_set_flag(ftdmchan->span, FTDM_SPAN_STATE_CHANGE);
        if (ftdmchan->span->pendingchans) {
                ftdm_queue_enqueue(ftdmchan->span->pendingchans, ftdmchan);
+       } else {
+               /* there is a potential deadlock here, if a signaling module is processing
+                * state changes while the ftdm_span_stop() function is called, the signaling
+                * thread will block until it can acquire the span lock, but the thread calling
+                * ftdm_span_stop() which holds the span lock is waiting on the signaling thread
+                * to finish ... The only reason to acquire the span lock is this flag, new
+                * signaling modules should use the pendingchans queue instead of this flag,
+                * as of today a few modules need still to be updated before we can get rid of
+                * this flag (ie, ftmod_libpri, ftmod_isdn, ftmod_analog) */
+               ftdm_set_flag_locked(ftdmchan->span, FTDM_SPAN_STATE_CHANGE);
        }
-       ftdm_mutex_unlock(ftdmchan->span->mutex);
 
        if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NONBLOCK)) {
                /* the channel should not block waiting for state processing */
index 2ed9fd04c57f4303741c3b2d10173e1c6f4c50cf..6df25fe4d2c0e70d318df2d72f765a2ef73fb845 100755 (executable)
@@ -173,6 +173,12 @@ typedef enum {
        FTDM_SPAN_SUSPENDED = (1 << 3),
        FTDM_SPAN_IN_THREAD = (1 << 4),
        FTDM_SPAN_STOP_THREAD = (1 << 5),
+       /*! Signaling modules set this flag to use fchan->pendingchans queue instead
+        *  of the FTDM_SPAN_STATE_CHANGE flag to detect when there is channels with
+        *  a state change pending in the span. If you set this member you can't rely
+        *  on FTDM_SPAN_STATE_CHANGE anymore and must use the queue only instead. This
+        *  is the new way of detecting state changes, new modules should always set this
+        *  flag, the old modules still relying on FTDM_SPAN_STATE_CHANGE should be updated */
        FTDM_SPAN_USE_CHAN_QUEUE = (1 << 6),
        FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7),
        FTDM_SPAN_USE_AV_RATE = (1 << 8),