Index: channels/iax2-parser.c =================================================================== --- channels/iax2-parser.c (revision 134125) +++ 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 40 #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,17 @@ 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; + } else { + ast_log(LOG_ERROR, "Frame cache full for thread %u\n", (unsigned int) pthread_self()); + ast_log_thread_info(); + } +#endif free(fr); -#endif } #if !defined(LOW_MEMORY) @@ -1030,7 +1044,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); Index: include/asterisk/utils.h =================================================================== --- include/asterisk/utils.h (revision 134125) +++ include/asterisk/utils.h (working copy) @@ -577,4 +577,6 @@ #define ast_assert(a) #endif +void ast_log_thread_info(void); + #endif /* _ASTERISK_UTILS_H */ Index: main/utils.c =================================================================== --- main/utils.c (revision 134125) +++ main/utils.c (working copy) @@ -867,6 +867,17 @@ char *name; }; +void ast_log_thread_info(void) +{ + struct thr_lock_info *lock_info; + + if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info)))) { + ast_log(LOG_ERROR, "Unable to get thread lock info\n"); + } + + ast_log(LOG_ERROR, "Thread '%s' ID '%u'\n", lock_info->thread_name, (unsigned int) lock_info->thread_id); +} + /* * on OS/X, pthread_cleanup_push() and pthread_cleanup_pop() * are odd macros which start and end a block, so they _must_ be