aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2008-03-03 15:50:43 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2008-03-03 15:50:43 +0000
commitb307b8a507544dacfff603e39a9299c6bab5b4f9 (patch)
tree68b69520c403cd9beee78cd2aa1334ad397b6b3a
parent5ce9b392d75b4fc1cb8c49b72b8a9c0b65567fa4 (diff)
Merge in some changes from team/russell/autoservice-nochans-1.4
These changes fix up some dubious code that I came across while auditing what happens in the autoservice thread when there are no channels currently in autoservice. 1) Change it so that autoservice thread doesn't keep looping around calling ast_waitfor_n() on 0 channels twice a second. Instead, use a thread condition so that the thread properly goes to sleep and does not wake up until a channel is put into autoservice. This actually fixes an interesting bug, as well. If the autoservice thread is already running (almost always is the case), then when the thread goes from having 0 channels to have 1 channel to autoservice, that channel would have to wait for up to 1/2 of a second to have the first frame read from it. 2) Fix up the code in ast_waitfor_nandfds() for when it gets called with no channels and no fds to poll() on, such as was the case with the previous code for the autoservice thread. In this case, the code would call alloca(0), and pass the result as the first argument to poll(). In this case, the 2nd argument to poll() specified that there were no fds, so this invalid pointer shouldn't actually get dereferenced, but, this code makes it explicit and ensures the pointers are NULL unless we have valid data to put there. (related to issue #12116) git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@105563 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--include/asterisk.h1
-rw-r--r--main/asterisk.c2
-rw-r--r--main/autoservice.c12
-rw-r--r--main/channel.c11
4 files changed, 21 insertions, 5 deletions
diff --git a/include/asterisk.h b/include/asterisk.h
index 08209bfb2..4fcb5f8ed 100644
--- a/include/asterisk.h
+++ b/include/asterisk.h
@@ -75,6 +75,7 @@ void dnsmgr_start_refresh(void); /*!< Provided by dnsmgr.c */
int dnsmgr_reload(void); /*!< Provided by dnsmgr.c */
void threadstorage_init(void); /*!< Provided by threadstorage.c */
int astobj2_init(void); /*! Provided by astobj2.c */
+void ast_autoservice_init(void); /*!< Provided by autoservice.c */
/* Many headers need 'ast_channel' to be defined */
struct ast_channel;
diff --git a/main/asterisk.c b/main/asterisk.c
index 52266b455..51423bf55 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -2896,6 +2896,8 @@ int main(int argc, char *argv[])
astobj2_init();
+ ast_autoservice_init();
+
if (load_modules(1)) {
printf(term_quit());
exit(1);
diff --git a/main/autoservice.c b/main/autoservice.c
index 0a641e97c..de14d82dd 100644
--- a/main/autoservice.c
+++ b/main/autoservice.c
@@ -64,6 +64,7 @@ struct asent {
};
static AST_LIST_HEAD_STATIC(aslist, asent);
+static ast_cond_t as_cond;
static pthread_t asthread = AST_PTHREADT_NULL;
@@ -98,6 +99,9 @@ static void *autoservice_run(void *ign)
* to get used again. */
as_chan_list_state++;
+ if (AST_LIST_EMPTY(&aslist))
+ ast_cond_wait(&as_cond, &aslist.lock);
+
AST_LIST_TRAVERSE(&aslist, as, list) {
if (!as->chan->_softhangup) {
if (x < MAX_AUTOMONS)
@@ -106,6 +110,7 @@ static void *autoservice_run(void *ign)
ast_log(LOG_WARNING, "Exceeded maximum number of automatic monitoring events. Fix autoservice.c\n");
}
}
+
AST_LIST_UNLOCK(&aslist);
chan = ast_waitfor_n(mons, x, &ms);
@@ -194,6 +199,8 @@ int ast_autoservice_start(struct ast_channel *chan)
ast_channel_unlock(chan);
AST_LIST_LOCK(&aslist);
+ if (AST_LIST_EMPTY(&aslist))
+ ast_cond_signal(&as_cond);
AST_LIST_INSERT_HEAD(&aslist, as, list);
AST_LIST_UNLOCK(&aslist);
@@ -276,3 +283,8 @@ int ast_autoservice_stop(struct ast_channel *chan)
return res;
}
+
+void ast_autoservice_init(void)
+{
+ ast_cond_init(&as_cond, NULL);
+}
diff --git a/main/channel.c b/main/channel.c
index 53f48c8a4..16881a3d5 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -1616,7 +1616,7 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
int *exception, int *outfd, int *ms)
{
struct timeval start = { 0 , 0 };
- struct pollfd *pfds;
+ struct pollfd *pfds = NULL;
int res;
long rms;
int x, y, max;
@@ -1627,11 +1627,12 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
struct fdmap {
int chan;
int fdno;
- } *fdmap;
+ } *fdmap = NULL;
- sz = n * AST_MAX_FDS + nfds;
- pfds = alloca(sizeof(*pfds) * sz);
- fdmap = alloca(sizeof(*fdmap) * sz);
+ if ((sz = n * AST_MAX_FDS + nfds)) {
+ pfds = alloca(sizeof(*pfds) * sz);
+ fdmap = alloca(sizeof(*fdmap) * sz);
+ }
if (outfd)
*outfd = -99999;