aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2010-11-08 21:58:13 +0000
committerjpeeler <jpeeler@f38db490-d61c-443f-a65b-d21fe96a405b>2010-11-08 21:58:13 +0000
commitf4712005a561e9013107147531ad776ad6e40283 (patch)
tree6f0c518abfe9845e32f0c56cf6b719e895ce7be3
parent3679c2b1c4768cb384968d345ad6c62a306768f0 (diff)
Fix playback failure when using IAX with the timerfd module.
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: http://svn.digium.com/svn/asterisk/branches/1.6.2@294277 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--include/asterisk/timing.h10
-rw-r--r--main/channel.c4
-rw-r--r--main/timing.c5
-rw-r--r--res/res_timing_timerfd.c9
4 files changed, 27 insertions, 1 deletions
diff --git a/include/asterisk/timing.h b/include/asterisk/timing.h
index d93f4f408..dd2a95d90 100644
--- a/include/asterisk/timing.h
+++ b/include/asterisk/timing.h
@@ -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
diff --git a/main/channel.c b/main/channel.c
index 7df055810..460c7bd62 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -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;
diff --git a/main/timing.c b/main/timing.c
index 751008ecf..7fc50c50a 100644
--- a/main/timing.c
+++ b/main/timing.c
@@ -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;
diff --git a/res/res_timing_timerfd.c b/res/res_timing_timerfd.c
index a62453e4d..51efa5173 100644
--- a/res/res_timing_timerfd.c
+++ b/res/res_timing_timerfd.c
@@ -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;
}