aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2005-09-13 21:59:45 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2005-09-13 21:59:45 +0000
commit7f896eb326eb12825b4d2192063bedbcc1acd193 (patch)
treefc71e427a8d14496d87e779d09549a9af24fd940
parent4ef986309141341c1c409bb0a4bc37967bd1adeb (diff)
check call limit in ast_pbx_start(), instead of waiting until background thread has been launched (needed for issue #5131)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@6568 f38db490-d61c-443f-a65b-d21fe96a405b
-rwxr-xr-xinclude/asterisk/pbx.h16
-rwxr-xr-xpbx.c79
2 files changed, 66 insertions, 29 deletions
diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h
index 9828aa6bb..f49eee16b 100755
--- a/include/asterisk/pbx.h
+++ b/include/asterisk/pbx.h
@@ -206,21 +206,27 @@ void ast_context_destroy(struct ast_context *con, const char *registrar);
*/
struct ast_context *ast_context_find(const char *name);
+enum ast_pbx_result {
+ AST_PBX_SUCCESS = 0,
+ AST_PBX_FAILED = -1,
+ AST_PBX_CALL_LIMIT = -2,
+};
+
/*! Create a new thread and start the PBX (or whatever) */
/*!
* \param c channel to start the pbx on
- * Starts a pbx thread on a given channel
- * It returns -1 on failure, and 0 on success
+ * \return Zero on success, non-zero on failure
*/
-int ast_pbx_start(struct ast_channel *c);
+enum ast_pbx_result ast_pbx_start(struct ast_channel *c);
/*! Execute the PBX in the current thread */
/*!
* \param c channel to run the pbx on
- * This executes the PBX on a given channel. It allocates a new
+ * \return Zero on success, non-zero on failure
+ * This executes the PBX on a given channel. It allocates a new
* PBX structure for the channel, and provides all PBX functionality.
*/
-int ast_pbx_run(struct ast_channel *c);
+enum ast_pbx_result ast_pbx_run(struct ast_channel *c);
/*!
* \param context context to add the extension to
diff --git a/pbx.c b/pbx.c
index a1eb07b99..6bae090ac 100755
--- a/pbx.c
+++ b/pbx.c
@@ -2407,56 +2407,87 @@ out:
return 0;
}
+/* Returns 0 on success, non-zero if call limit was reached */
+static int increase_call_count(const struct ast_channel *c)
+{
+ int failed = 0;
+
+ ast_mutex_lock(&maxcalllock);
+ if (option_maxcalls) {
+ if (countcalls >= option_maxcalls) {
+ ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
+ failed = -1;
+ }
+ }
+ if (!failed)
+ countcalls++;
+ ast_mutex_unlock(&maxcalllock);
+
+ return failed;
+}
+
+static void decrease_call_count(void)
+{
+ ast_mutex_lock(&maxcalllock);
+ if (countcalls > 0)
+ countcalls--;
+ ast_mutex_unlock(&maxcalllock);
+}
+
static void *pbx_thread(void *data)
{
/* Oh joyeous kernel, we're a new thread, with nothing to do but
answer this channel and get it going.
*/
+ /* NOTE:
+ The launcher of this function _MUST_ increment 'countcalls'
+ before invoking the function; it will be decremented when the
+ PBX has finished running on the channel
+ */
struct ast_channel *c = data;
- ast_pbx_run(c);
+
+ __ast_pbx_run(c);
+ decrease_call_count();
+
pthread_exit(NULL);
+
return NULL;
}
-int ast_pbx_start(struct ast_channel *c)
+enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
{
pthread_t t;
pthread_attr_t attr;
+
if (!c) {
ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
- return -1;
+ return AST_PBX_FAILED;
}
+ if (increase_call_count(c))
+ return AST_PBX_CALL_LIMIT;
+
/* Start a new thread, and get something handling this channel. */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (ast_pthread_create(&t, &attr, pbx_thread, c)) {
ast_log(LOG_WARNING, "Failed to create new channel thread\n");
- return -1;
+ return AST_PBX_FAILED;
}
- return 0;
+
+ return AST_PBX_SUCCESS;
}
-int ast_pbx_run(struct ast_channel *c)
+enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
{
- int res = 0;
- ast_mutex_lock(&maxcalllock);
- if (option_maxcalls) {
- if (countcalls >= option_maxcalls) {
- ast_log(LOG_NOTICE, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
- res = -1;
- }
- }
- if (!res)
- countcalls++;
- ast_mutex_unlock(&maxcalllock);
- if (!res) {
- res = __ast_pbx_run(c);
- ast_mutex_lock(&maxcalllock);
- if (countcalls > 0)
- countcalls--;
- ast_mutex_unlock(&maxcalllock);
- }
+ enum ast_pbx_result res = AST_PBX_SUCCESS;
+
+ if (increase_call_count(c))
+ return AST_PBX_CALL_LIMIT;
+
+ res = __ast_pbx_run(c);
+ decrease_call_count();
+
return res;
}