aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/asterisk/_private.h1
-rw-r--r--main/asterisk.c2
-rw-r--r--main/autoservice.c56
-rw-r--r--main/channel.c11
4 files changed, 44 insertions, 26 deletions
diff --git a/include/asterisk/_private.h b/include/asterisk/_private.h
index 33ba83593..b477d0e93 100644
--- a/include/asterisk/_private.h
+++ b/include/asterisk/_private.h
@@ -33,6 +33,7 @@ int ast_device_state_engine_init(void); /*!< Provided by devicestate.c */
int astobj2_init(void); /*!< Provided by astobj2.c */
int ast_file_init(void); /*!< Provided by file.c */
int ast_features_init(void); /*!< Provided by features.c */
+void ast_autoservice_init(void); /*!< Provided by autoservice.c */
/*!
* \brief Reload asterisk modules.
diff --git a/main/asterisk.c b/main/asterisk.c
index 5de317fc5..2548d4316 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -3186,6 +3186,8 @@ int main(int argc, char *argv[])
astobj2_init();
+ ast_autoservice_init();
+
if (load_modules(1)) { /* Load modules, pre-load only */
printf(term_quit());
exit(1);
diff --git a/main/autoservice.c b/main/autoservice.c
index 7fb86dad7..74b1015ef 100644
--- a/main/autoservice.c
+++ b/main/autoservice.c
@@ -30,6 +30,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/time.h>
#include <signal.h>
+#include "asterisk/_private.h" /* prototype for ast_autoservice_init() */
+
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
#include "asterisk/sched.h"
@@ -56,7 +58,8 @@ struct asent {
AST_LIST_ENTRY(asent) list;
};
-static AST_RWLIST_HEAD_STATIC(aslist, asent);
+static AST_LIST_HEAD_STATIC(aslist, asent);
+static ast_cond_t as_cond;
static pthread_t asthread = AST_PTHREADT_NULL;
@@ -67,14 +70,14 @@ static void defer_frame(struct ast_channel *chan, struct ast_frame *f)
struct ast_frame *dup_f;
struct asent *as;
- AST_RWLIST_WRLOCK(&aslist);
- AST_RWLIST_TRAVERSE(&aslist, as, list) {
+ AST_LIST_LOCK(&aslist);
+ AST_LIST_TRAVERSE(&aslist, as, list) {
if (as->chan != chan)
continue;
if ((dup_f = ast_frdup(f)))
AST_LIST_INSERT_TAIL(&as->dtmf_frames, dup_f, frame_list);
}
- AST_RWLIST_UNLOCK(&aslist);
+ AST_LIST_UNLOCK(&aslist);
}
static void *autoservice_run(void *ign)
@@ -84,13 +87,16 @@ static void *autoservice_run(void *ign)
struct asent *as;
int x = 0, ms = 500;
- AST_RWLIST_RDLOCK(&aslist);
+ AST_LIST_LOCK(&aslist);
/* At this point, we know that no channels that have been removed are going
* to get used again. */
as_chan_list_state++;
- AST_RWLIST_TRAVERSE(&aslist, as, list) {
+ if (AST_LIST_EMPTY(&aslist))
+ ast_cond_wait(&as_cond, &aslist.lock);
+
+ AST_LIST_TRAVERSE(&aslist, as, list) {
if (!ast_check_hangup(as->chan)) {
if (x < MAX_AUTOMONS)
mons[x++] = as->chan;
@@ -98,7 +104,8 @@ static void *autoservice_run(void *ign)
ast_log(LOG_WARNING, "Exceeded maximum number of automatic monitoring events. Fix autoservice.c\n");
}
}
- AST_RWLIST_UNLOCK(&aslist);
+
+ AST_LIST_UNLOCK(&aslist);
if ((chan = ast_waitfor_n(mons, x, &ms))) {
struct ast_frame *f = ast_read(chan);
@@ -158,14 +165,14 @@ int ast_autoservice_start(struct ast_channel *chan)
int res = 0;
struct asent *as;
- AST_RWLIST_WRLOCK(&aslist);
- AST_RWLIST_TRAVERSE(&aslist, as, list) {
+ AST_LIST_LOCK(&aslist);
+ AST_LIST_TRAVERSE(&aslist, as, list) {
if (as->chan == chan) {
as->use_count++;
break;
}
}
- AST_RWLIST_UNLOCK(&aslist);
+ AST_LIST_UNLOCK(&aslist);
if (as) {
/* Entry exists, autoservice is already handling this channel */
@@ -185,18 +192,20 @@ int ast_autoservice_start(struct ast_channel *chan)
ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
ast_channel_unlock(chan);
- AST_RWLIST_WRLOCK(&aslist);
- AST_RWLIST_INSERT_HEAD(&aslist, as, list);
- AST_RWLIST_UNLOCK(&aslist);
+ 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);
if (asthread == AST_PTHREADT_NULL) { /* need start the thread */
if (ast_pthread_create_background(&asthread, NULL, autoservice_run, NULL)) {
ast_log(LOG_WARNING, "Unable to create autoservice thread :(\n");
/* There will only be a single member in the list at this point,
the one we just added. */
- AST_RWLIST_WRLOCK(&aslist);
- AST_RWLIST_REMOVE(&aslist, as, list);
- AST_RWLIST_UNLOCK(&aslist);
+ AST_LIST_LOCK(&aslist);
+ AST_LIST_REMOVE(&aslist, as, list);
+ AST_LIST_UNLOCK(&aslist);
free(as);
res = -1;
} else
@@ -218,7 +227,7 @@ int ast_autoservice_stop(struct ast_channel *chan)
AST_LIST_HEAD_INIT_NOLOCK(&dtmf_frames);
- AST_RWLIST_WRLOCK(&aslist);
+ AST_LIST_LOCK(&aslist);
/* Save the autoservice channel list state. We _must_ verify that the channel
* list has been rebuilt before we return. Because, after we return, the channel
@@ -226,9 +235,9 @@ int ast_autoservice_stop(struct ast_channel *chan)
* it after its gone! */
chan_list_state = as_chan_list_state;
- AST_RWLIST_TRAVERSE_SAFE_BEGIN(&aslist, as, list) {
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&aslist, as, list) {
if (as->chan == chan) {
- AST_RWLIST_REMOVE_CURRENT(list);
+ AST_LIST_REMOVE_CURRENT(list);
as->use_count--;
if (as->use_count)
break;
@@ -241,12 +250,12 @@ int ast_autoservice_stop(struct ast_channel *chan)
break;
}
}
- AST_RWLIST_TRAVERSE_SAFE_END;
+ AST_LIST_TRAVERSE_SAFE_END;
if (removed && asthread != AST_PTHREADT_NULL)
pthread_kill(asthread, SIGURG);
- AST_RWLIST_UNLOCK(&aslist);
+ AST_LIST_UNLOCK(&aslist);
if (!removed)
return 0;
@@ -268,3 +277,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 a7e158d32..5742341c4 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -1771,7 +1771,7 @@ struct ast_channel *ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds,
#endif
{
struct timeval start = { 0 , 0 };
- struct pollfd *pfds;
+ struct pollfd *pfds = NULL;
int res;
long rms;
int x, y, max;
@@ -1782,11 +1782,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;