From 35d6da06a63eefa970f562cdfdbf081add770522 Mon Sep 17 00:00:00 2001 From: George Joseph Date: Tue, 15 Oct 2024 11:11:28 -0600 Subject: [PATCH] core_unreal.c: Fix memory leak in ast_unreal_new_channels() 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 --- main/core_unreal.c | 5 ++--- main/stream.c | 9 ++++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/main/core_unreal.c b/main/core_unreal.c index d43272c874..42166d273a 100644 --- a/main/core_unreal.c +++ b/main/core_unreal.c @@ -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 */ diff --git a/main/stream.c b/main/stream.c index e464c5e8d8..ea6544e0ad 100644 --- a/main/stream.c +++ b/main/stream.c @@ -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(