aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-03-02 23:34:13 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-03-02 23:34:13 +0000
commit7853685bebf3619ded417c462aa2f023e9c76a5e (patch)
tree0c40232062460a3deb7a9db912c0331ae2ebef04
parent3d9ed4987972cb6e0e1c718e76618a6c6dc85485 (diff)
Move ast_waitfor() down to avoid the results of the API call becoming stale.
This call to ast_waitfor() was being done way too soon in this section of code. Specifically, there was code in between the call to waitfor and the code that uses the result that puts the channel in autoservice. By putting the channel in autoservice, the previous results of ast_waitfor() become meaningless, as the autoservice thread will do it's own ast_waitfor() and ast_read() on the channel. So, when we came back out of autoservice and eventually hit the block of code that calls ast_read() on the channel, there may not actually be any input on the channel available. Even though the previous call to ast_waitfor() in app_meetme said there was input, the autoservice thread has since serviced the channel for some period of time. This bug manifested itself while dvossel was doing some testing of MeetMe in Asterisk trunk. He was using the timerfd timing module. When the code hit ast_read() erroneously, it determined that it must have been called because of input on the timer fd, as chan->fdno was set to AST_TIMING_FD, since that was the cause of the last legitimate call to ast_read() done by autoservice. In this test, an IAX2 channel was calling into the MeetMe conference. It was _much_ more likely to be seen with an IAX2 channel because of the way audio is handled. Every audio frame that comes in results in a call to ast_queue_frame(), which then uses ast_timer_enable_continuous() to notify the channel thread that a frame is waiting to be handled. So, the chances of ast_waitfor() indicating that a channel needs servicing due to a timer event on an IAX2 event is very high. Finally, it is interesting to note that if a different timing interface was being used, this bug would probably not be noticed. When ast_read() is called and erroneously thinks that there is a timer event to handle, it calls the ast_timer_ack() function. The pthread and dahdi timing modules handle the ack() function being called when there is no event by simply ignoring it. In the case of the timerfd module, it results in a read() on the timer fd that will block forever, as there is no data to read. This caused Asterisk to lock up very quickly. Thanks to dvossel and mmichelson for the fun debugging session. :-) git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@179532 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--apps/app_meetme.c7
1 files changed, 3 insertions, 4 deletions
diff --git a/apps/app_meetme.c b/apps/app_meetme.c
index f36496271..4d6a9ce50 100644
--- a/apps/app_meetme.c
+++ b/apps/app_meetme.c
@@ -1909,12 +1909,9 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
ast_waitstream(chan, "");
}
- c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
-
-
/* Update the struct with the actual confflags */
user->userflags = confflags;
-
+
if (confflags & CONFFLAG_WAITMARKED) {
if(currentmarked == 0) {
if (lastmarked != 0) {
@@ -2036,6 +2033,8 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
if (ast_check_hangup(chan))
break;
+ c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
+
if (c) {
char dtmfstr[2] = "";