]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Fix playback failure when using IAX with the timerfd module.
authorJeff Peeler <jpeeler@digium.com>
Mon, 8 Nov 2010 21:58:13 +0000 (21:58 +0000)
committerJeff Peeler <jpeeler@digium.com>
Mon, 8 Nov 2010 21:58:13 +0000 (21:58 +0000)
To fix this issue the alert pipe will now be used when the timerfd module is
in use. There appeared to be a race that was not solved by adding locking in the
timerfd module, but needed to be there anyway. The race was between the timer
being put in non-continuous mode in ast_read on the channel thread and the IAX
frame scheduler queuing a frame which would enable continuous mode before the
non-continuous mode event was read. This race for now is simply avoided.

(closes issue #18110)
Reported by: tpanton
Tested by: tpanton

I put tested by tpanton because it was tested on his hardware. Thanks for the
remote access to debug this issue!

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.2@294277 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/timing.h
main/channel.c
main/timing.c
res/res_timing_timerfd.c

index d93f4f408cf1f4f75415c96b9ce37745c9f8faf0..dd2a95d906e83e30b01ee8b3ff6fcceb26b98106 100644 (file)
@@ -216,6 +216,16 @@ enum ast_timer_event ast_timer_get_event(const struct ast_timer *handle);
  */
 unsigned int ast_timer_get_max_rate(const struct ast_timer *handle);
 
+/*!
+ * \brief Get name of timer in use
+ *
+ * \param handle timer handle returned by timer_open()
+ *
+ * \return name of timer
+ * \since 1.6.2
+ */
+const char *ast_timer_get_name(const struct ast_timer *handle);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
index 7df0558101e6190031ae7723fe08b0168c1fb4d6..460c7bd62375480bd9ad10d80eb8ecb7779ed9b6 100644 (file)
@@ -820,7 +820,9 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
        }
 
        if ((tmp->timer = ast_timer_open())) {
-               needqueue = 0;
+               if (strcmp(ast_timer_get_name(tmp->timer), "timerfd")) {
+                       needqueue = 0;
+               }
                tmp->timingfd = ast_timer_fd(tmp->timer);
        } else {
                tmp->timingfd = -1;
index 751008ecf96fe8522582ffefc523d4564f353dd9..7fc50c50a8505130904149820cf8fe46fde6e0cf 100644 (file)
@@ -205,6 +205,11 @@ unsigned int ast_timer_get_max_rate(const struct ast_timer *handle)
        return res;
 }
 
+const char *ast_timer_get_name(const struct ast_timer *handle)
+{
+       return handle->holder->iface->name;
+}
+
 static char *timing_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        struct ast_timer *timer;
index a62453e4d72e09bc1482f3e807fec04dbd7eeb11..51efa51732dca8d4419cd85781b290931c59819f 100644 (file)
@@ -140,6 +140,7 @@ static int timerfd_timer_set_rate(int handle, unsigned int rate)
                ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
                return -1;
        }
+       ao2_lock(our_timer);
 
        our_timer->saved_timer.it_value.tv_sec = 0;
        our_timer->saved_timer.it_value.tv_nsec = rate ? (long) (1000000000 / rate) : 0L;
@@ -150,6 +151,7 @@ static int timerfd_timer_set_rate(int handle, unsigned int rate)
                res = timerfd_settime(handle, 0, &our_timer->saved_timer, NULL);
        }
 
+       ao2_unlock(our_timer);
        ao2_ref(our_timer, -1);
 
        return res;
@@ -191,17 +193,20 @@ static int timerfd_timer_enable_continuous(int handle)
                ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
                return -1;
        }
+       ao2_lock(our_timer);
 
        if (our_timer->is_continuous) {
                /*It's already in continous mode, no need to do
                 * anything further
                 */
+               ao2_unlock(our_timer);
                ao2_ref(our_timer, -1);
                return 0;
        }
 
        res = timerfd_settime(handle, 0, &continuous_timer, &our_timer->saved_timer);
        our_timer->is_continuous = 1;
+       ao2_unlock(our_timer);
        ao2_ref(our_timer, -1);
        return res;
 }
@@ -217,6 +222,7 @@ static int timerfd_timer_disable_continuous(int handle)
                ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
                return -1;
        }
+       ao2_lock(our_timer);
 
        if(!our_timer->is_continuous) {
                /* No reason to do anything if we're not
@@ -229,6 +235,7 @@ static int timerfd_timer_disable_continuous(int handle)
        res = timerfd_settime(handle, 0, &our_timer->saved_timer, NULL);
        our_timer->is_continuous = 0;
        memset(&our_timer->saved_timer, 0, sizeof(our_timer->saved_timer));
+       ao2_unlock(our_timer);
        ao2_ref(our_timer, -1);
        return res;
 }
@@ -244,6 +251,7 @@ static enum ast_timer_event timerfd_timer_get_event(int handle)
                ast_log(LOG_ERROR, "Couldn't find timer with handle %d\n", handle);
                return -1;
        }
+       ao2_lock(our_timer);
 
        if (our_timer->is_continuous) {
                res = AST_TIMING_EVENT_CONTINUOUS;
@@ -251,6 +259,7 @@ static enum ast_timer_event timerfd_timer_get_event(int handle)
                res = AST_TIMING_EVENT_EXPIRED;
        }
 
+       ao2_unlock(our_timer);
        ao2_ref(our_timer, -1);
        return res;
 }