<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
Ok, we will try the patch, and also we will print in the ast_log the
address of the cache  used  to find wich thread  is leaking memory,
since each thread has his cache we can match the threads with the cache
addresses.<br>
<br>
We are debugging this issue in an asterisk server with only one call so
we don't think that is there more than one thread using iax data. I am
going to apply the patch and try again to see if the problem is still
there and if there is more than one thread calling
iax_frame_new/iax_frame_free.<br>
<br>
<br>
I have filled bug number 0013160 with this issue.<br>
<br>
Thanks.<br>
Octavio.<br>
<br>
<br>
<br>
 <br>
<br>
Russell Bryant escribió:
<blockquote cite="mid:4889EC5E.8080606@digium.com" type="cite">
  <pre wrap="">Octavio Ascanio Su‡árez wrote:
  </pre>
  <blockquote type="cite">
    <pre wrap="">I am Octavio, I am working with Eric in this problem. We have added some 
ast_log in iax_frame_free and iax_frame_new we have seen that 
iax_frame_new dont find a block of 160 bytes in the linked list when 
iax_frame_free has added it previously.
    </pre>
  </blockquote>
  <pre wrap=""><!---->
Keep in mind that just because you saw a frame of that size go into 
iax_frame_free, does not mean that is available for the next call to 
iax_frame_new.  There is a cache of available frames _per thread_.  So, 
if the call to iax_frame_free is done from a different thread than the 
call to iax_frame_new, then this behavior would be expected.

It is possible that there is a thread (or number of a specific type of 
threads) in chan_iax2 which has code that frees frames, but does not 
allocate them.  If that is the case, then the frame cache for that 
thread would grow for forever.

If that is the issue we're facing, then the following patch would avoid 
the infinite leak.  However, a full solution would be to add an argument 
for iax_frame_free which hints that the frame shouldn't be cached when 
we know it will never be pulled out of the cache.

Index: channels/iax2-parser.c
===================================================================
--- channels/iax2-parser.c        (revision 133577)
+++ channels/iax2-parser.c        (working copy)
@@ -58,7 +58,14 @@

  /*! \brief This is just so iax_frames, a list head struct for holding 
a list of
   *  iax_frame structures, is defined. */
-AST_LIST_HEAD_NOLOCK(iax_frames, iax_frame);
+AST_LIST_HEAD_NOLOCK(iax_frame_list, iax_frame);
+
+struct iax_frames {
+        struct iax_frame_list list;
+        size_t size;
+};
+
+#define FRAME_CACHE_MAX_SIZE        20
  #endif

  static void internaloutput(const char *str)
@@ -957,10 +964,11 @@

          /* Attempt to get a frame from this thread's cache */
          if ((iax_frames = ast_threadstorage_get(&amp;frame_cache, 
sizeof(*iax_frames)))) {
-                AST_LIST_TRAVERSE_SAFE_BEGIN(iax_frames, fr, list) {
+                AST_LIST_TRAVERSE_SAFE_BEGIN(&amp;iax_frames-&gt;list, fr, list) {
                          if (fr-&gt;afdatalen &gt;= datalen) {
                                  size_t afdatalen = fr-&gt;afdatalen;
-                                AST_LIST_REMOVE_CURRENT(iax_frames, list);
+                                AST_LIST_REMOVE_CURRENT(&amp;iax_frames-&gt;list, list);
+                                iax_frames-&gt;size--;
                                  memset(fr, 0, sizeof(*fr));
                                  fr-&gt;afdatalen = afdatalen;
                                  break;
@@ -1017,11 +1025,14 @@
                  return;
          }

-        fr-&gt;direction = 0;
-        AST_LIST_INSERT_HEAD(iax_frames, fr, list);
-#else
+        if (iax_frames-&gt;size &lt; FRAME_CACHE_MAX_SIZE) {
+                fr-&gt;direction = 0;
+                AST_LIST_INSERT_HEAD(&amp;iax_frames-&gt;list, fr, list);
+                iax_frames-&gt;size++;
+                return;
+        }
+#endif
          free(fr);
-#endif
  }

  #if !defined(LOW_MEMORY)
@@ -1030,7 +1041,7 @@
          struct iax_frames *frames = data;
          struct iax_frame *cur;

-        while ((cur = AST_LIST_REMOVE_HEAD(frames, list)))
+        while ((cur = AST_LIST_REMOVE_HEAD(&amp;frames-&gt;list, list)))
                  free(cur);

          free(frames);


  </pre>
</blockquote>
</body>
</html>