From 9f6f77014f95db3eb092ae2abef01296d322944c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 8 Jan 2008 18:35:51 +0000 Subject: [PATCH] leak protection, better than mighty putty git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@7141 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_core.h | 16 ++- src/include/switch_module_interfaces.h | 3 + .../mod_conference/mod_conference.c | 111 +++++++++--------- .../mod_local_stream/mod_local_stream.c | 16 ++- src/switch_core_file.c | 13 +- 5 files changed, 93 insertions(+), 66 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 50125b558c..226b3409a2 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1135,12 +1135,16 @@ SWITCH_DECLARE(void) switch_core_db_test_reactive(switch_core_db_t *db, char *te \return SWITCH_STATUS_SUCCESS if the file is opened \note the loadable module used is chosen based on the file extension */ -SWITCH_DECLARE(switch_status_t) switch_core_file_open(_In_ switch_file_handle_t *fh, - _In_z_ const char *file_path, - _In_ uint8_t channels, - _In_ uint32_t rate, - _In_ unsigned int flags, - _In_opt_ switch_memory_pool_t *pool); +SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, const char *func, int line, + _In_ switch_file_handle_t *fh, + _In_z_ const char *file_path, + _In_ uint8_t channels, + _In_ uint32_t rate, + _In_ unsigned int flags, + _In_opt_ switch_memory_pool_t *pool); +#define switch_core_file_open(_fh, _file_path, _channels, _rate, _flags, _pool) \ + switch_core_perform_file_open(__FILE__, __SWITCH_FUNC__, __LINE__, _fh, _file_path, _channels, _rate, _flags, _pool) + /*! \brief Read media from a file handle \param fh the file handle to read from (must be initilized by you memset all 0 for read, fill in channels and rate for write) diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index cc9e5cdf29..62bb76766d 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -301,6 +301,9 @@ struct switch_file_handle { switch_buffer_t *buffer; switch_byte_t *dbuf; switch_size_t dbuflen; + const char *file; + const char *func; + int line; }; /*! \brief Abstract interface to an asr module */ diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 6a9e0341b6..976803aae0 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -979,64 +979,63 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t * thread, switch_event_fire(&event); } - switch_core_timer_destroy(&timer); + + + switch_mutex_lock(conference->mutex); + conference_stop_file(conference, FILE_STOP_ASYNC); + conference_stop_file(conference, FILE_STOP_ALL); + /* Close Unused Handles */ + if (conference->fnode) { + conference_file_node_t *fnode, *cur; + switch_memory_pool_t *pool; + + fnode = conference->fnode; + while (fnode) { + cur = fnode; + fnode = fnode->next; + + if (cur->type != NODE_TYPE_SPEECH) { + switch_core_file_close(&cur->fh); + } + + pool = cur->pool; + switch_core_destroy_memory_pool(&pool); + } + conference->fnode = NULL; + } + + if (conference->async_fnode) { + switch_memory_pool_t *pool; + switch_core_file_close(&conference->async_fnode->fh); + pool = conference->async_fnode->pool; + conference->async_fnode = NULL; + switch_core_destroy_memory_pool(&pool); + } + + switch_mutex_lock(conference->member_mutex); + for (imember = conference->members; imember; imember = imember->next) { + switch_channel_t *channel; + + if (!switch_test_flag(imember, MFLAG_NOCHANNEL)) { + channel = switch_core_session_get_channel(imember->session); + + /* add this little bit to preserve the bridge cause code in case of an early media call that */ + /* never answers */ + if (switch_test_flag(conference, CFLAG_ANSWERED)) { + switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + } else { + /* put actual cause code from outbound channel hangup here */ + switch_channel_hangup(channel, conference->bridge_hangup_cause); + } + } + + switch_clear_flag_locked(imember, MFLAG_RUNNING); + } + switch_mutex_unlock(conference->member_mutex); + switch_mutex_unlock(conference->mutex); if (switch_test_flag(conference, CFLAG_DESTRUCT)) { - - switch_mutex_lock(conference->mutex); - conference_stop_file(conference, FILE_STOP_ASYNC); - conference_stop_file(conference, FILE_STOP_ALL); - /* Close Unused Handles */ - if (conference->fnode) { - conference_file_node_t *fnode, *cur; - switch_memory_pool_t *pool; - - fnode = conference->fnode; - while (fnode) { - cur = fnode; - fnode = fnode->next; - - if (cur->type != NODE_TYPE_SPEECH) { - switch_core_file_close(&cur->fh); - } - - pool = cur->pool; - switch_core_destroy_memory_pool(&pool); - } - conference->fnode = NULL; - } - - if (conference->async_fnode) { - switch_memory_pool_t *pool; - switch_core_file_close(&conference->async_fnode->fh); - pool = conference->async_fnode->pool; - conference->async_fnode = NULL; - switch_core_destroy_memory_pool(&pool); - } - - switch_mutex_lock(conference->member_mutex); - for (imember = conference->members; imember; imember = imember->next) { - switch_channel_t *channel; - - if (!switch_test_flag(imember, MFLAG_NOCHANNEL)) { - channel = switch_core_session_get_channel(imember->session); - - /* add this little bit to preserve the bridge cause code in case of an early media call that */ - /* never answers */ - if (switch_test_flag(conference, CFLAG_ANSWERED)) { - switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); - } else { - /* put actual cause code from outbound channel hangup here */ - switch_channel_hangup(channel, conference->bridge_hangup_cause); - } - } - - switch_clear_flag_locked(imember, MFLAG_RUNNING); - } - switch_mutex_unlock(conference->member_mutex); - - switch_mutex_unlock(conference->mutex); - + switch_core_timer_destroy(&timer); switch_mutex_lock(globals.hash_mutex); switch_core_hash_delete(globals.conference_hash, conference->name); switch_mutex_unlock(globals.hash_mutex); diff --git a/src/mod/formats/mod_local_stream/mod_local_stream.c b/src/mod/formats/mod_local_stream/mod_local_stream.c index ce5c33c981..9275d9cb7a 100644 --- a/src/mod/formats/mod_local_stream/mod_local_stream.c +++ b/src/mod/formats/mod_local_stream/mod_local_stream.c @@ -51,6 +51,9 @@ struct local_stream_context { switch_mutex_t *audio_mutex; switch_buffer_t *audio_buffer; int err; + const char *file; + const char *func; + int line; struct local_stream_context *next; }; typedef struct local_stream_context local_stream_context_t; @@ -191,14 +194,20 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void switch_buffer_write(audio_buffer, abuf, olen * 2); used = switch_buffer_inuse(audio_buffer); - + if (used >= source->prebuf || (source->total && used > source->samples * 2)) { used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2); if (source->total) { + switch_mutex_lock(source->mutex); for (cp = source->context_list; cp; cp = cp->next) { switch_mutex_lock(cp->audio_mutex); - switch_buffer_write(cp->audio_buffer, dist_buf, used); + if (switch_buffer_inuse(cp->audio_buffer) > source->samples * 128) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Leaking stream handle! [%s() %s:%d]\n", cp->func, cp->file, cp->line); + switch_buffer_zero(cp->audio_buffer); + } else { + switch_buffer_write(cp->audio_buffer, dist_buf, used); + } switch_mutex_unlock(cp->audio_mutex); } switch_mutex_unlock(source->mutex); @@ -277,6 +286,9 @@ static switch_status_t local_stream_file_open(switch_file_handle_t *handle, cons } context->source = source; + context->file = handle->file; + context->func = handle->func; + context->line = handle->line; switch_mutex_lock(source->mutex); context->next = source->context_list; diff --git a/src/switch_core_file.c b/src/switch_core_file.c index 0b1c5d74b1..2d05328449 100644 --- a/src/switch_core_file.c +++ b/src/switch_core_file.c @@ -34,8 +34,13 @@ #include #include "private/switch_core_pvt.h" -SWITCH_DECLARE(switch_status_t) switch_core_file_open(switch_file_handle_t *fh, - const char *file_path, uint8_t channels, uint32_t rate, unsigned int flags, switch_memory_pool_t *pool) +SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, const char *func, int line, + switch_file_handle_t *fh, + const char *file_path, + uint8_t channels, + uint32_t rate, + unsigned int flags, + switch_memory_pool_t *pool) { char *ext; switch_status_t status; @@ -63,6 +68,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_open(switch_file_handle_t *fh, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid file format [%s] for [%s]!\n", ext, file_path); return SWITCH_STATUS_GENERR; } + + fh->file = file; + fh->func = func; + fh->line = line; fh->flags = flags; if (pool) {