check call limit in ast_pbx_start(), instead of waiting until background thread has...
authorKevin P. Fleming <kpfleming@digium.com>
Tue, 13 Sep 2005 21:59:45 +0000 (21:59 +0000)
committerKevin P. Fleming <kpfleming@digium.com>
Tue, 13 Sep 2005 21:59:45 +0000 (21:59 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6568 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/pbx.h
pbx.c

index 9828aa6..f49eee1 100755 (executable)
@@ -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 a1eb07b..6bae090 100755 (executable)
--- 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;
 }