<p>Richard Mudgett has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/7195">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">core: Add cache_media_frames debugging option.<br><br>The media frame cache gets in the way of finding use after free errors of<br>media frames. Tools like valgrind and MALLOC_DEBUG don't know when a<br>frame is released because it gets put into the cache instead of being<br>freed.<br><br>* Added the "cache_media_frames" option to asterisk.conf. Disabling the<br>option helps track down media frame mismanagement when using valgrind or<br>MALLOC_DEBUG. The cache gets in the way of determining if the frame is<br>used after free and who freed it. NOTE: This option has no effect when<br>Asterisk is compiled with the LOW_MEMORY compile time option enabled<br>because the cache code does not exist.<br><br>To disable the media frame cache simply disable the cache_media_frames<br>option in asterisk.conf and restart Asterisk.<br><br>Sample asterisk.conf setting:<br>[options]<br>cache_media_frames=no<br><br>ASTERISK-27413<br><br>Change-Id: I0ab2ce0f4547cccf2eb214901835c2d951b78c00<br>---<br>M CHANGES<br>M channels/iax2/parser.c<br>M configs/samples/asterisk.conf.sample<br>M include/asterisk/options.h<br>M main/asterisk.c<br>M main/frame.c<br>6 files changed, 45 insertions(+), 9 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/95/7195/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/CHANGES b/CHANGES<br>index 74ebf64..7dd1aac 100644<br>--- a/CHANGES<br>+++ b/CHANGES<br>@@ -12,6 +12,15 @@<br> --- Functionality changes from Asterisk 13.18.0 to Asterisk 13.19.0 ----------<br> ------------------------------------------------------------------------------<br> <br>+Core<br>+------------------<br>+ * Added the "cache_media_frames" option to asterisk.conf. Disabling the option<br>+ helps track down media frame mismanagement when using valgrind or<br>+ MALLOC_DEBUG. The cache gets in the way of determining if the frame is<br>+ used after free and who freed it. NOTE: This option has no effect when<br>+ Asterisk is compiled with the LOW_MEMORY compile time option enabled because<br>+ the cache code does not exist.<br>+<br> res_pjsip<br> ------------------<br> * The "identify_by" on endpoints can now be set to "ip" to restrict an endpoint<br>diff --git a/channels/iax2/parser.c b/channels/iax2/parser.c<br>index 2a3eabf..09c1323 100644<br>--- a/channels/iax2/parser.c<br>+++ b/channels/iax2/parser.c<br>@@ -1298,7 +1298,9 @@<br> ast_atomic_fetchadd_int(&frames, -1);<br> <br> #if !defined(LOW_MEMORY)<br>- if (!fr->cacheable || !(iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {<br>+ if (!fr->cacheable<br>+ || !ast_opt_cache_media_frames<br>+ || !(iax_frames = ast_threadstorage_get(&frame_cache, sizeof(*iax_frames)))) {<br> ast_free(fr);<br> return;<br> }<br>diff --git a/configs/samples/asterisk.conf.sample b/configs/samples/asterisk.conf.sample<br>index 38cee25..e57ee10 100644<br>--- a/configs/samples/asterisk.conf.sample<br>+++ b/configs/samples/asterisk.conf.sample<br>@@ -43,6 +43,15 @@<br> ;minmemfree = 1 ; In MBs, Asterisk stops accepting new calls if<br> ; the amount of free memory falls below this<br> ; watermark.<br>+;cache_media_frames = yes ; Cache media frames for performance<br>+ ; Disable this option to help track down media frame<br>+ ; mismanagement when using valgrind or MALLOC_DEBUG.<br>+ ; The cache gets in the way of determining if the<br>+ ; frame is used after being freed and who freed it.<br>+ ; NOTE: This option has no effect when Asterisk is<br>+ ; compiled with the LOW_MEMORY compile time option<br>+ ; enabled because the cache code does not exist.<br>+ ; Default yes<br> ;cache_record_files = yes ; Cache recorded sound files to another<br> ; directory during recording.<br> ;record_cache_dir = /tmp ; Specify cache directory (used in conjunction<br>diff --git a/include/asterisk/options.h b/include/asterisk/options.h<br>index 950764e..c64de2f 100644<br>--- a/include/asterisk/options.h<br>+++ b/include/asterisk/options.h<br>@@ -76,6 +76,8 @@<br> AST_OPT_FLAG_DONT_WARN = (1 << 18),<br> /*! End CDRs before the 'h' extension */<br> AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN = (1 << 19),<br>+ /*! Cache media frames for performance */<br>+ AST_OPT_FLAG_CACHE_MEDIA_FRAMES = (1 << 20),<br> /*! Always fork, even if verbose or debug settings are non-zero */<br> AST_OPT_FLAG_ALWAYS_FORK = (1 << 21),<br> /*! Disable log/verbose output to remote consoles */<br>@@ -99,7 +101,7 @@<br> };<br> <br> /*! These are the options that set by default when Asterisk starts */<br>-#define AST_DEFAULT_OPTIONS AST_OPT_FLAG_TRANSCODE_VIA_SLIN<br>+#define AST_DEFAULT_OPTIONS (AST_OPT_FLAG_TRANSCODE_VIA_SLIN | AST_OPT_FLAG_CACHE_MEDIA_FRAMES)<br> <br> #define ast_opt_exec_includes ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES)<br> #define ast_opt_no_fork ast_test_flag(&ast_options, AST_OPT_FLAG_NO_FORK)<br>@@ -116,6 +118,7 @@<br> #define ast_opt_stdexten_macro ast_test_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO)<br> #define ast_opt_dump_core ast_test_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE)<br> #define ast_opt_cache_record_files ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES)<br>+#define ast_opt_cache_media_frames ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_MEDIA_FRAMES)<br> #define ast_opt_timestamp ast_test_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP)<br> #define ast_opt_override_config ast_test_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG)<br> #define ast_opt_reconnect ast_test_flag(&ast_options, AST_OPT_FLAG_RECONNECT)<br>diff --git a/main/asterisk.c b/main/asterisk.c<br>index 8cbbe93..0eaf8dd 100644<br>--- a/main/asterisk.c<br>+++ b/main/asterisk.c<br>@@ -676,6 +676,9 @@<br> ast_cli(a->fd, " Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) ? "Enabled" : "Disabled");<br> ast_cli(a->fd, " Generic PLC: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled");<br> ast_cli(a->fd, " Min DTMF duration:: %u\n", option_dtmfminduration);<br>+#if !defined(LOW_MEMORY)<br>+ ast_cli(a->fd, " Cache media frames: %s\n", ast_opt_cache_media_frames ? "Enabled" : "Disabled");<br>+#endif<br> <br> if (ast_option_rtpptdynamic == AST_RTP_PT_LAST_REASSIGN) {<br> ast_cli(a->fd, " RTP dynamic payload types: %u,%u-%u\n",<br>@@ -3827,6 +3830,11 @@<br> /* Cache recorded sound files to another directory during recording */<br> } else if (!strcasecmp(v->name, "cache_record_files")) {<br> ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);<br>+#if !defined(LOW_MEMORY)<br>+ /* Cache media frames for performance */<br>+ } else if (!strcasecmp(v->name, "cache_media_frames")) {<br>+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_MEDIA_FRAMES);<br>+#endif<br> /* Specify cache directory */<br> } else if (!strcasecmp(v->name, "record_cache_dir")) {<br> ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);<br>diff --git a/main/frame.c b/main/frame.c<br>index 4261b04..db2b967 100644<br>--- a/main/frame.c<br>+++ b/main/frame.c<br>@@ -122,14 +122,18 @@<br> return;<br> <br> #if !defined(LOW_MEMORY)<br>- if (cache && fr->mallocd == AST_MALLOCD_HDR) {<br>+ if (fr->mallocd == AST_MALLOCD_HDR<br>+ && cache<br>+ && ast_opt_cache_media_frames) {<br> /* Cool, only the header is malloc'd, let's just cache those for now<br> * to keep things simple... */<br> struct ast_frame_cache *frames;<br>- if ((frames = ast_threadstorage_get(&frame_cache, sizeof(*frames))) &&<br>- (frames->size < FRAME_CACHE_MAX_SIZE)) {<br>- if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||<br>- (fr->frametype == AST_FRAME_IMAGE)) {<br>+<br>+ frames = ast_threadstorage_get(&frame_cache, sizeof(*frames));<br>+ if (frames && frames->size < FRAME_CACHE_MAX_SIZE) {<br>+ if (fr->frametype == AST_FRAME_VOICE<br>+ || fr->frametype == AST_FRAME_VIDEO<br>+ || fr->frametype == AST_FRAME_IMAGE) {<br> ao2_cleanup(fr->subclass.format);<br> }<br> <br>@@ -149,8 +153,9 @@<br> ast_free((void *) fr->src);<br> }<br> if (fr->mallocd & AST_MALLOCD_HDR) {<br>- if ((fr->frametype == AST_FRAME_VOICE) || (fr->frametype == AST_FRAME_VIDEO) ||<br>- (fr->frametype == AST_FRAME_IMAGE)) {<br>+ if (fr->frametype == AST_FRAME_VOICE<br>+ || fr->frametype == AST_FRAME_VIDEO<br>+ || fr->frametype == AST_FRAME_IMAGE) {<br> ao2_cleanup(fr->subclass.format);<br> }<br> <br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/7195">change 7195</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/7195"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I0ab2ce0f4547cccf2eb214901835c2d951b78c00 </div>
<div style="display:none"> Gerrit-Change-Number: 7195 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Richard Mudgett <rmudgett@digium.com> </div>