]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
stream: Make the topology a reference counted object.
authorJoshua Colp <jcolp@digium.com>
Fri, 20 Apr 2018 23:12:53 +0000 (23:12 +0000)
committerJoshua Colp <jcolp@digium.com>
Thu, 3 May 2018 16:31:56 +0000 (16:31 +0000)
The stream topology has no lock of its own resulting in
another lock protecting it in some way (for example the
channel lock). If multiple channels are being juggled at
the same time this can be problematic. This change makes
the topology a reference counted object instead which
guarantees it will remain valid even without the channel
lock being held.

Change-Id: I4f4d3dd856a033ed55fe218c3a4fab364afedb03

bridges/bridge_softmix.c
include/asterisk/stream.h
main/stream.c

index 23dc548467d3246681b83283d1e6d752203d7ed6..46b27f104206ca0053324c8c5d558dd5e842856b 100644 (file)
@@ -2159,15 +2159,7 @@ static void softmix_bridge_stream_topology_changed(struct ast_bridge *bridge, st
                ast_bridge_channel_lock(participant);
                ast_channel_lock(participant->chan);
 
-               topology = ast_channel_get_stream_topology(participant->chan);
-               if (topology) {
-                       /*
-                        * Sigh.  We have to clone to avoid deadlock in
-                        * map_source_to_destinations() because topology
-                        * is not an ao2 object.
-                        */
-                       topology = ast_stream_topology_clone(topology);
-               }
+               topology = ao2_bump(ast_channel_get_stream_topology(participant->chan));
                if (!topology) {
                        /* Oh, my, we are in trouble. */
                        ast_channel_unlock(participant->chan);
index 0a5550b5ee59030ae19d98638b36cb2c9b417f6d..ade740d19da84062a29562db59b3848779bd3a48 100644 (file)
@@ -306,6 +306,8 @@ void ast_stream_set_rtp_codecs(struct ast_stream *stream, struct ast_rtp_codecs
  * \retval NULL failure
  *
  * \since 15
+ *
+ * \note This returns an ao2 refcounted object
  */
 struct ast_stream_topology *ast_stream_topology_alloc(void);
 
@@ -318,6 +320,8 @@ struct ast_stream_topology *ast_stream_topology_alloc(void);
  * \retval NULL failure
  *
  * \since 15
+ *
+ * \note This returns an ao2 refcounted object
  */
 struct ast_stream_topology *ast_stream_topology_clone(
        const struct ast_stream_topology *topology);
@@ -337,7 +341,7 @@ int ast_stream_topology_equal(const struct ast_stream_topology *left,
        const struct ast_stream_topology *right);
 
 /*!
- * \brief Destroy a stream topology
+ * \brief Unreference and destroy a stream topology
  *
  * \param topology The topology of streams
  *
index dd3e765f6447ea6c805acd70458b2ed5a46de15e..47415bffffb74d7702656de76ab67c018c5b7abb 100644 (file)
@@ -344,18 +344,26 @@ void ast_stream_set_rtp_codecs(struct ast_stream *stream, struct ast_rtp_codecs
        stream->rtp_codecs = rtp_codecs;
 }
 
+static void stream_topology_destroy(void *data)
+{
+       struct ast_stream_topology *topology = data;
+
+       AST_VECTOR_CALLBACK_VOID(&topology->streams, ast_stream_free);
+       AST_VECTOR_FREE(&topology->streams);
+}
+
 #define TOPOLOGY_INITIAL_STREAM_COUNT 2
 struct ast_stream_topology *ast_stream_topology_alloc(void)
 {
        struct ast_stream_topology *topology;
 
-       topology = ast_calloc(1, sizeof(*topology));
+       topology = ao2_alloc_options(sizeof(*topology), stream_topology_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
        if (!topology) {
                return NULL;
        }
 
        if (AST_VECTOR_INIT(&topology->streams, TOPOLOGY_INITIAL_STREAM_COUNT)) {
-               ast_free(topology);
+               ao2_ref(topology, -1);
                topology = NULL;
        }
 
@@ -440,13 +448,7 @@ int ast_stream_topology_equal(const struct ast_stream_topology *left,
 
 void ast_stream_topology_free(struct ast_stream_topology *topology)
 {
-       if (!topology) {
-               return;
-       }
-
-       AST_VECTOR_CALLBACK_VOID(&topology->streams, ast_stream_free);
-       AST_VECTOR_FREE(&topology->streams);
-       ast_free(topology);
+       ao2_cleanup(topology);
 }
 
 int ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)