]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
core_unreal.c: Fix memory leak in ast_unreal_new_channels()
authorGeorge Joseph <gjoseph@sangoma.com>
Tue, 15 Oct 2024 17:11:28 +0000 (11:11 -0600)
committerAsterisk Development Team <asteriskteam@digium.com>
Thu, 14 Nov 2024 20:01:34 +0000 (20:01 +0000)
When the channel tech is multistream capable, the reference to
chan_topology was passed to the new channel.  When the channel tech
isn't multistream capable, the reference to chan_topology was never
released.  "Local" channels are multistream capable so it didn't
affect them but the confbridge "CBAnn" and the bridge_media
"Recorder" channels are not so they caused a leak every time one
of them was created.

Also added tracing to ast_stream_topology_alloc() and
stream_topology_destroy() to assist with debugging.

Resolves: #938
(cherry picked from commit e434203810e188b79351f18bfb2a915e68772589)

main/core_unreal.c
main/stream.c

index d43272c8742419209507fa8006efc0f14c88a4e3..42166d273a15739210e7312bbdc3c8321b1b8b3e 100644 (file)
@@ -1169,7 +1169,7 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
        struct ast_assigned_ids id2 = {NULL, NULL};
        int generated_seqno = ast_atomic_fetchadd_int((int *) &name_sequence, +1);
        int i;
-       struct ast_stream_topology *chan_topology;
+       RAII_VAR(struct ast_stream_topology *, chan_topology, NULL, ast_stream_topology_free);
        struct ast_stream *stream;
 
        /* set unique ids for the two channels */
@@ -1221,7 +1221,6 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
                "%s/%s-%08x;1", tech->type, p->name, (unsigned)generated_seqno);
        if (!owner) {
                ast_log(LOG_WARNING, "Unable to allocate owner channel structure\n");
-               ast_stream_topology_free(chan_topology);
                return NULL;
        }
 
@@ -1295,7 +1294,7 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
        ast_channel_nativeformats_set(chan, p->reqcap);
 
        if (ast_channel_is_multistream(chan)) {
-               ast_channel_set_stream_topology(chan, chan_topology);
+               ast_channel_set_stream_topology(chan, ao2_bump(chan_topology));
        }
 
        /* Format was already determined when setting up owner */
index e464c5e8d85479a0da236c72ecf9c0d12221ddd6..ea6544e0ad8185e4be94046c3a2f00325b764a5f 100644 (file)
@@ -641,27 +641,30 @@ struct ast_stream *ast_stream_create_resolved(struct ast_stream *pending_stream,
 static void stream_topology_destroy(void *data)
 {
        struct ast_stream_topology *topology = data;
+       SCOPE_ENTER(4, "Topology: %p: %s\n", topology, ast_str_tmp(128, ast_stream_topology_to_str(topology, &STR_TMP)));
 
        AST_VECTOR_CALLBACK_VOID(&topology->streams, ast_stream_free);
        AST_VECTOR_FREE(&topology->streams);
+       SCOPE_EXIT_RTN("Destroyed: %p\n", topology);
 }
 
 #define TOPOLOGY_INITIAL_STREAM_COUNT 2
 struct ast_stream_topology *ast_stream_topology_alloc(void)
 {
        struct ast_stream_topology *topology;
+       SCOPE_ENTER(4, "Topology Create\n");
 
        topology = ao2_alloc_options(sizeof(*topology), stream_topology_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
        if (!topology) {
-               return NULL;
+               SCOPE_EXIT_RTN_VALUE(NULL, "Allocation failed\n");
        }
 
        if (AST_VECTOR_INIT(&topology->streams, TOPOLOGY_INITIAL_STREAM_COUNT)) {
                ao2_ref(topology, -1);
-               topology = NULL;
+               SCOPE_EXIT_RTN_VALUE(NULL, "Vector init failed\n");
        }
 
-       return topology;
+       SCOPE_EXIT_RTN_VALUE(topology, "Created: %p\n", topology);
 }
 
 struct ast_stream_topology *ast_stream_topology_clone(