core: Add cache_media_frames debugging option.

The media frame cache gets in the way of finding use after free errors of
media frames.  Tools like valgrind and MALLOC_DEBUG don't know when a
frame is released because it gets put into the cache instead of being
freed.

* Added the "cache_media_frames" option to asterisk.conf.  Disabling the
option helps track down media frame mismanagement when using valgrind or
MALLOC_DEBUG.  The cache gets in the way of determining if the frame is
used after free and who freed it.  NOTE: This option has no effect when
Asterisk is compiled with the LOW_MEMORY compile time option enabled
because the cache code does not exist.

To disable the media frame cache simply disable the cache_media_frames
option in asterisk.conf and restart Asterisk.

Sample asterisk.conf setting:
[options]
cache_media_frames=no

ASTERISK-27413

Change-Id: I0ab2ce0f4547cccf2eb214901835c2d951b78c00
This commit is contained in:
Richard Mudgett
2017-11-11 13:01:47 -06:00
parent 1250b7c664
commit 507d9b5f9e
6 changed files with 45 additions and 9 deletions

View File

@@ -122,14 +122,18 @@ static void __frame_free(struct ast_frame *fr, int cache)
return;
#if !defined(LOW_MEMORY)
if (cache && fr->mallocd == AST_MALLOCD_HDR) {
if (fr->mallocd == AST_MALLOCD_HDR
&& cache
&& ast_opt_cache_media_frames) {
/* Cool, only the header is malloc'd, let's just cache those for now
* to keep things simple... */
struct ast_frame_cache *frames;
if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) &&
(frames->size < FRAME_CACHE_MAX_SIZE)) {
if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
(fr->frametype == AST_FRAME_IMAGE)) {
frames = ast_threadstorage_get(&frame_cache, sizeof(*frames));
if (frames && frames->size < FRAME_CACHE_MAX_SIZE) {
if (fr->frametype == AST_FRAME_VOICE
|| fr->frametype == AST_FRAME_VIDEO
|| fr->frametype == AST_FRAME_IMAGE) {
ao2_cleanup(fr->subclass.format);
}
@@ -149,8 +153,9 @@ static void __frame_free(struct ast_frame *fr, int cache)
ast_free((void *) fr->src);
}
if (fr->mallocd & AST_MALLOCD_HDR) {
if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||
(fr->frametype == AST_FRAME_IMAGE)) {
if (fr->frametype == AST_FRAME_VOICE
|| fr->frametype == AST_FRAME_VIDEO
|| fr->frametype == AST_FRAME_IMAGE) {
ao2_cleanup(fr->subclass.format);
}