]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
autoservice: Don't start channel autoservice if the thread is a user interface.
authorRichard Mudgett <rmudgett@digium.com>
Mon, 18 Jun 2018 23:04:54 +0000 (18:04 -0500)
committerRichard Mudgett <rmudgett@digium.com>
Tue, 19 Jun 2018 19:18:12 +0000 (14:18 -0500)
Executing dialplan functions from either AMI or ARI by getting a variable
could place the channel into autoservice.  However, these user interface
threads do not handle the channel's media so we wind up with two threads
attempting to handle the media.

There can be one and only one thread handling a channel's media at a time.
Otherwise, we don't know which thread is going to handle the media frames.

ASTERISK-27625

Change-Id: If2dc94ce15ddabf923ed1e2a65ea0ef56e013e49

include/asterisk/utils.h
main/autoservice.c
main/tcptls.c
main/utils.c

index b6fd9e825a2f9deef75c77602823c9d301fafb01..1fc7b42f84b7bc6498d787ace69823ccf8deafde 100644 (file)
@@ -1194,4 +1194,22 @@ enum ast_fd_flag_operation {
 int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op,
        const char *file, int lineno, const char *function);
 
+/*!
+ * \brief Set the current thread's user interface status.
+ *
+ * \param is_user_interface Non-zero to mark the thread as a user interface.
+ *
+ * \return 0 if successfuly marked current thread.
+ * \return Non-zero if marking current thread failed.
+ */
+int ast_thread_user_interface_set(int is_user_interface);
+
+/*!
+ * \brief Indicates whether the current thread is a user interface
+ *
+ * \return True (non-zero) if thread is a user interface.
+ * \return False (zero) if thread is not a user interface.
+ */
+int ast_thread_is_user_interface(void);
+
 #endif /* _ASTERISK_UTILS_H */
index cd7388b7ddab6d6f380885733e011b1e7dfbbf05..8ff2cb56e16da8e1d737b2d1d12ff3e5296ececa 100644 (file)
@@ -202,6 +202,13 @@ int ast_autoservice_start(struct ast_channel *chan)
        int res = 0;
        struct asent *as;
 
+       if (ast_thread_is_user_interface()) {
+               /* User interface threads do not handle channel media. */
+               ast_debug(1, "Thread is a user interface, not putting channel %s into autoservice\n",
+                       ast_channel_name(chan));
+               return 0;
+       }
+
        AST_LIST_LOCK(&aslist);
        AST_LIST_TRAVERSE(&aslist, as, list) {
                if (as->chan == chan) {
@@ -263,6 +270,13 @@ int ast_autoservice_stop(struct ast_channel *chan)
        struct ast_frame *f;
        int chan_list_state;
 
+       if (ast_thread_is_user_interface()) {
+               /* User interface threads do not handle channel media. */
+               ast_debug(1, "Thread is a user interface, not removing channel %s from autoservice\n",
+                       ast_channel_name(chan));
+               return 0;
+       }
+
        AST_LIST_LOCK(&aslist);
 
        /* Save the autoservice channel list state.  We _must_ verify that the channel
index f5557307e01b3181a3120adf48e1f3c9015fd201..3ba52ff6a3b17c7afa2028579823a1d93623c411 100644 (file)
@@ -134,6 +134,19 @@ static void *handle_tcptls_connection(void *data)
                return NULL;
        }
 
+       /*
+        * TCP/TLS connections are associated with external protocols which can
+        * be considered to be user interfaces (even for SIP messages), and
+        * will not handle channel media.  This may need to be pushed down into
+        * the individual protocol handlers, but this seems like a good start.
+        */
+       if (ast_thread_user_interface_set(1)) {
+               ast_log(LOG_ERROR, "Failed to set user interface status; killing connection\n");
+               ast_tcptls_close_session_file(tcptls_session);
+               ao2_ref(tcptls_session, -1);
+               return NULL;
+       }
+
        if (tcptls_session->parent->tls_cfg) {
 #ifdef DO_SSL
                if (ast_iostream_start_tls(&tcptls_session->stream, tcptls_session->parent->tls_cfg->ssl_ctx, tcptls_session->client) < 0) {
index dae994d62b467d6806acf33758e6979b4bb00ada..b249f6a7d94b659c71d074cf8dd3cc68c573a7df 100644 (file)
@@ -2793,3 +2793,38 @@ int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op,
 
        return 0;
 }
+
+/*!
+ * \brief A thread local indicating whether the current thread is a user interface.
+ */
+AST_THREADSTORAGE(thread_user_interface_tl);
+
+int ast_thread_user_interface_set(int is_user_interface)
+{
+       int *thread_user_interface;
+
+       thread_user_interface = ast_threadstorage_get(
+               &thread_user_interface_tl, sizeof(*thread_user_interface));
+       if (thread_user_interface == NULL) {
+               ast_log(LOG_ERROR, "Error setting user interface status for current thread\n");
+               return -1;
+       }
+
+       *thread_user_interface = !!is_user_interface;
+       return 0;
+}
+
+int ast_thread_is_user_interface(void)
+{
+       int *thread_user_interface;
+
+       thread_user_interface = ast_threadstorage_get(
+               &thread_user_interface_tl, sizeof(*thread_user_interface));
+       if (thread_user_interface == NULL) {
+               ast_log(LOG_ERROR, "Error checking thread's user interface status\n");
+               /* On error, assume that we are not a user interface thread */
+               return 0;
+       }
+
+       return *thread_user_interface;
+}