<!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(&frame_cache,
sizeof(*iax_frames)))) {
-                AST_LIST_TRAVERSE_SAFE_BEGIN(iax_frames, fr, list) {
+                AST_LIST_TRAVERSE_SAFE_BEGIN(&iax_frames->list, fr, list) {
                        if (fr->afdatalen >= datalen) {
                                size_t afdatalen = fr->afdatalen;
-                                AST_LIST_REMOVE_CURRENT(iax_frames, list);
+                                AST_LIST_REMOVE_CURRENT(&iax_frames->list, list);
+                                iax_frames->size--;
                                memset(fr, 0, sizeof(*fr));
                                fr->afdatalen = afdatalen;
                                break;
@@ -1017,11 +1025,14 @@
                return;
        }
-        fr->direction = 0;
-        AST_LIST_INSERT_HEAD(iax_frames, fr, list);
-#else
+        if (iax_frames->size < FRAME_CACHE_MAX_SIZE) {
+                fr->direction = 0;
+                AST_LIST_INSERT_HEAD(&iax_frames->list, fr, list);
+                iax_frames->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(&frames->list, list)))
                free(cur);
        free(frames);
</pre>
</blockquote>
</body>
</html>