Merge "Revert "PJSIP_CONTACT: add missing argument documentation""
[asterisk/asterisk.git] / main / astmm.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2012, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Memory Management
22  *
23  * \author Mark Spencer <markster@digium.com>
24  * \author Richard Mudgett <rmudgett@digium.com>
25  */
26
27 /*** MODULEINFO
28         <support_level>core</support_level>
29  ***/
30
31 #define ASTMM_LIBC ASTMM_IGNORE
32 #include "asterisk.h"
33
34 #include "asterisk/_private.h"
35 #include "asterisk/logger.h"
36
37 /*!
38  * \brief DEBUG_CHAOS returns failure randomly
39  *
40  * DEBUG_CHAOS_RETURN(failure); can be used to fake
41  * failure of functions such as memory allocation,
42  * for the purposes of testing failure handling.
43  */
44 #ifdef DEBUG_CHAOS
45 #ifndef DEBUG_CHAOS_ALLOC_CHANCE
46 #define DEBUG_CHAOS_ALLOC_CHANCE 100000
47 #endif
48 /* Could #define DEBUG_CHAOS_ENABLE ast_fully_booted */
49 #ifndef DEBUG_CHAOS_ENABLE
50 #define DEBUG_CHAOS_ENABLE 1
51 #endif
52 #define DEBUG_CHAOS_RETURN(CHANCE, FAILURE) \
53         do { \
54                 if ((DEBUG_CHAOS_ENABLE) && (ast_random() % CHANCE == 0)) { \
55                         return FAILURE; \
56                 } \
57         } while (0)
58 #else
59 #define DEBUG_CHAOS_RETURN(c,f)
60 #endif
61
62 #if defined(STANDALONE) || defined(STANDALONE2)
63 #define ast_log_safe ast_log
64 #endif
65
66 #if defined(MALLOC_DEBUG) && !defined(STANDALONE) && !defined(STANDALONE2)
67 #define __AST_DEBUG_MALLOC
68 #endif
69
70 #define MALLOC_FAILURE_MSG \
71         ast_log_safe(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file)
72
73 #if defined(__AST_DEBUG_MALLOC)
74
75 #include "asterisk/paths.h"     /* use ast_config_AST_LOG_DIR */
76 #include <stddef.h>
77 #include <time.h>
78
79 #include "asterisk/cli.h"
80 #include "asterisk/lock.h"
81 #include "asterisk/strings.h"
82 #include "asterisk/unaligned.h"
83 #include "asterisk/backtrace.h"
84
85 /*!
86  * The larger the number the faster memory can be freed.
87  * However, more memory then is used for the regions[] hash
88  * table.
89  */
90 #define SOME_PRIME 1567
91
92 enum func_type {
93         FUNC_CALLOC = 1,
94         FUNC_MALLOC,
95         FUNC_REALLOC,
96         FUNC_STRDUP,
97         FUNC_STRNDUP,
98         FUNC_VASPRINTF,
99         FUNC_ASPRINTF
100 };
101
102 #define FENCE_MAGIC             0xfeedbabe      /*!< Allocated memory high/low fence overwrite check. */
103 #define FREED_MAGIC             0xdeaddead      /*!< Freed memory wipe filler. */
104 #define MALLOC_FILLER   0x55            /*!< Malloced memory filler.  Must not be zero. */
105
106 static FILE *mmlog;
107
108 struct ast_region {
109         AST_LIST_ENTRY(ast_region) node;
110         struct ast_bt *bt;
111         size_t len;
112         unsigned int cache;             /* region was allocated as part of a cache pool */
113         unsigned int lineno;
114         enum func_type which;
115         char file[64];
116         char func[40];
117         /*!
118          * \brief Lower guard fence.
119          *
120          * \note Must be right before data[].
121          *
122          * \note Padding between fence and data[] is irrelevent because
123          * data[] is used to fill in the lower fence check value and not
124          * the fence member.  The fence member is to ensure that there
125          * is space reserved for the fence check value.
126          */
127         unsigned int fence;
128         /*!
129          * \brief Location of the requested malloc block to return.
130          *
131          * \note Must have the same alignment that malloc returns.
132          * i.e., It is suitably aligned for any kind of varible.
133          */
134         unsigned char data[0] __attribute__((aligned));
135 };
136
137 /*! Hash table of lists of active allocated memory regions. */
138 static struct ast_region *regions[SOME_PRIME];
139
140 /*! Number of freed regions to keep around to delay actually freeing them. */
141 #define FREED_MAX_COUNT         1500
142
143 /*! Maximum size of a minnow block */
144 #define MINNOWS_MAX_SIZE        50
145
146 struct ast_freed_regions {
147         /*! Memory regions that have been freed. */
148         struct ast_region *regions[FREED_MAX_COUNT];
149         /*! Next index into freed regions[] to use. */
150         int index;
151 };
152
153 /*! Large memory blocks that have been freed. */
154 static struct ast_freed_regions whales;
155 /*! Small memory blocks that have been freed. */
156 static struct ast_freed_regions minnows;
157
158 enum summary_opts {
159         /*! No summary at exit. */
160         SUMMARY_OFF,
161         /*! Bit set if summary by line at exit. */
162         SUMMARY_BY_LINE = (1 << 0),
163         /*! Bit set if summary by function at exit. */
164         SUMMARY_BY_FUNC = (1 << 1),
165         /*! Bit set if summary by file at exit. */
166         SUMMARY_BY_FILE = (1 << 2),
167 };
168
169 /*! Summary options of unfreed regions at exit. */
170 static enum summary_opts atexit_summary;
171 /*! Nonzero if the unfreed regions are listed at exit. */
172 static int atexit_list;
173 /*! Nonzero if the memory allocation backtrace is enabled. */
174 static int backtrace_enabled;
175
176 #define HASH(a)         (((unsigned long)(a)) % ARRAY_LEN(regions))
177
178 /*! Tracking this mutex will cause infinite recursion, as the mutex tracking
179  *  code allocates memory */
180 AST_MUTEX_DEFINE_STATIC_NOTRACKING(reglock);
181
182 #define astmm_log(...)                               \
183         do {                                         \
184                 fprintf(stderr, __VA_ARGS__);        \
185                 if (mmlog) {                         \
186                         fprintf(mmlog, __VA_ARGS__); \
187                         fflush(mmlog);               \
188                 }                                    \
189         } while (0)
190
191 static void print_backtrace(struct ast_bt *bt, struct ast_cli_args *a)
192 {
193         int i = 0;
194         struct ast_vector_string *strings;
195
196         if (!bt) {
197                 return;
198         }
199
200         if ((strings = ast_bt_get_symbols(bt->addresses, bt->num_frames))) {
201                 if (a) {
202                         ast_cli(a->fd, "Memory allocation backtrace:\n");
203                 } else {
204                         astmm_log("Memory allocation backtrace:\n");
205                 }
206                 for (i = 3; i < AST_VECTOR_SIZE(strings) - 2; i++) {
207                         if (a) {
208                                 ast_cli(a->fd, "#%d: %s\n", i - 3, AST_VECTOR_GET(strings, i));
209                         } else {
210                                 astmm_log("#%d: %s\n", i - 3, AST_VECTOR_GET(strings, i));
211                         }
212                 }
213                 ast_bt_free_symbols(strings);
214         }
215 }
216
217 /*!
218  * \internal
219  *
220  * \note If DO_CRASH is not defined then the function returns.
221  *
222  * \return Nothing
223  */
224 static void my_do_crash(void)
225 {
226         /*
227          * Give the logger a chance to get the message out, just in case
228          * we abort(), or Asterisk crashes due to whatever problem just
229          * happened.
230          */
231         usleep(1);
232         ast_do_crash();
233 }
234
235 static void *__ast_alloc_region(size_t size, const enum func_type which, const char *file, int lineno, const char *func, unsigned int cache)
236 {
237         struct ast_region *reg;
238         unsigned int *fence;
239         int hash;
240
241         DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
242
243         if (!(reg = malloc(size + sizeof(*reg) + sizeof(*fence)))) {
244                 astmm_log("Memory Allocation Failure - '%d' bytes at %s %s() line %d\n",
245                         (int) size, file, func, lineno);
246                 return NULL;
247         }
248
249         reg->len = size;
250         reg->cache = cache;
251         reg->lineno = lineno;
252         reg->which = which;
253         reg->bt = backtrace_enabled ? ast_bt_create() : NULL;
254         ast_copy_string(reg->file, file, sizeof(reg->file));
255         ast_copy_string(reg->func, func, sizeof(reg->func));
256
257         /*
258          * Init lower fence.
259          *
260          * We use the bytes just preceeding reg->data and not reg->fence
261          * because there is likely to be padding between reg->fence and
262          * reg->data for reg->data alignment.
263          */
264         fence = (unsigned int *) (reg->data - sizeof(*fence));
265         *fence = FENCE_MAGIC;
266
267         /* Init higher fence. */
268         fence = (unsigned int *) (reg->data + reg->len);
269         put_unaligned_uint32(fence, FENCE_MAGIC);
270
271         hash = HASH(reg->data);
272         ast_mutex_lock(&reglock);
273         AST_LIST_NEXT(reg, node) = regions[hash];
274         regions[hash] = reg;
275         ast_mutex_unlock(&reglock);
276
277         return reg->data;
278 }
279
280 /*!
281  * \internal
282  * \brief Wipe the region payload data with a known value.
283  *
284  * \param reg Region block to be wiped.
285  *
286  * \return Nothing
287  */
288 static void region_data_wipe(struct ast_region *reg)
289 {
290         void *end;
291         unsigned int *pos;
292
293         /*
294          * Wipe the lower fence, the payload, and whatever amount of the
295          * higher fence that falls into alignment with the payload.
296          */
297         end = reg->data + reg->len;
298         for (pos = &reg->fence; (void *) pos <= end; ++pos) {
299                 *pos = FREED_MAGIC;
300         }
301 }
302
303 /*!
304  * \internal
305  * \brief Check the region payload data for memory corruption.
306  *
307  * \param reg Region block to be checked.
308  *
309  * \return Nothing
310  */
311 static void region_data_check(struct ast_region *reg)
312 {
313         void *end;
314         unsigned int *pos;
315
316         /*
317          * Check the lower fence, the payload, and whatever amount of
318          * the higher fence that falls into alignment with the payload.
319          */
320         end = reg->data + reg->len;
321         for (pos = &reg->fence; (void *) pos <= end; ++pos) {
322                 if (*pos != FREED_MAGIC) {
323                         astmm_log("WARNING: Memory corrupted after free of %p allocated at %s %s() line %d\n",
324                                 reg->data, reg->file, reg->func, reg->lineno);
325                         print_backtrace(reg->bt, NULL);
326                         my_do_crash();
327                         break;
328                 }
329         }
330 }
331
332 /*!
333  * \internal
334  * \brief Flush the circular array of freed regions.
335  *
336  * \param freed Already freed region blocks storage.
337  *
338  * \return Nothing
339  */
340 static void freed_regions_flush(struct ast_freed_regions *freed)
341 {
342         int idx;
343         struct ast_region *old;
344
345         ast_mutex_lock(&reglock);
346         for (idx = 0; idx < ARRAY_LEN(freed->regions); ++idx) {
347                 old = freed->regions[idx];
348                 freed->regions[idx] = NULL;
349                 if (old) {
350                         region_data_check(old);
351                         free(old);
352                 }
353         }
354         freed->index = 0;
355         ast_mutex_unlock(&reglock);
356 }
357
358 /*!
359  * \internal
360  * \brief Delay freeing a region block.
361  *
362  * \param freed Already freed region blocks storage.
363  * \param reg Region block to be freed.
364  *
365  * \return Nothing
366  */
367 static void region_free(struct ast_freed_regions *freed, struct ast_region *reg)
368 {
369         struct ast_region *old;
370
371         region_data_wipe(reg);
372
373         ast_mutex_lock(&reglock);
374         old = freed->regions[freed->index];
375         freed->regions[freed->index] = reg;
376
377         ++freed->index;
378         if (ARRAY_LEN(freed->regions) <= freed->index) {
379                 freed->index = 0;
380         }
381         ast_mutex_unlock(&reglock);
382
383         if (old) {
384                 region_data_check(old);
385                 old->bt = ast_bt_destroy(old->bt);
386                 free(old);
387         }
388 }
389
390 /*!
391  * \internal
392  * \brief Remove a region from the active regions.
393  *
394  * \param ptr Region payload data pointer.
395  *
396  * \retval region on success.
397  * \retval NULL if not found.
398  */
399 static struct ast_region *region_remove(void *ptr)
400 {
401         int hash;
402         struct ast_region *reg;
403         struct ast_region *prev = NULL;
404
405         hash = HASH(ptr);
406
407         ast_mutex_lock(&reglock);
408         for (reg = regions[hash]; reg; reg = AST_LIST_NEXT(reg, node)) {
409                 if (reg->data == ptr) {
410                         if (prev) {
411                                 AST_LIST_NEXT(prev, node) = AST_LIST_NEXT(reg, node);
412                         } else {
413                                 regions[hash] = AST_LIST_NEXT(reg, node);
414                         }
415                         break;
416                 }
417                 prev = reg;
418         }
419         ast_mutex_unlock(&reglock);
420
421         return reg;
422 }
423
424 /*!
425  * \internal
426  * \brief Check the fences of a region.
427  *
428  * \param reg Region block to check.
429  *
430  * \return Nothing
431  */
432 static void region_check_fences(struct ast_region *reg)
433 {
434         unsigned int *fence;
435
436         /*
437          * We use the bytes just preceeding reg->data and not reg->fence
438          * because there is likely to be padding between reg->fence and
439          * reg->data for reg->data alignment.
440          */
441         fence = (unsigned int *) (reg->data - sizeof(*fence));
442         if (*fence != FENCE_MAGIC) {
443                 astmm_log("WARNING: Low fence violation of %p allocated at %s %s() line %d\n",
444                         reg->data, reg->file, reg->func, reg->lineno);
445                 print_backtrace(reg->bt, NULL);
446                 my_do_crash();
447         }
448         fence = (unsigned int *) (reg->data + reg->len);
449         if (get_unaligned_uint32(fence) != FENCE_MAGIC) {
450                 astmm_log("WARNING: High fence violation of %p allocated at %s %s() line %d\n",
451                         reg->data, reg->file, reg->func, reg->lineno);
452                 print_backtrace(reg->bt, NULL);
453                 my_do_crash();
454         }
455 }
456
457 /*!
458  * \internal
459  * \brief Check the fences of all regions currently allocated.
460  *
461  * \return Nothing
462  */
463 static void regions_check_all_fences(void)
464 {
465         int idx;
466         struct ast_region *reg;
467
468         ast_mutex_lock(&reglock);
469         for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
470                 for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) {
471                         region_check_fences(reg);
472                 }
473         }
474         ast_mutex_unlock(&reglock);
475 }
476
477 void __ast_free(void *ptr, const char *file, int lineno, const char *func)
478 {
479         struct ast_region *reg;
480
481         if (!ptr) {
482                 return;
483         }
484
485         reg = region_remove(ptr);
486         if (reg) {
487                 region_check_fences(reg);
488
489                 if (reg->len <= MINNOWS_MAX_SIZE) {
490                         region_free(&minnows, reg);
491                 } else {
492                         region_free(&whales, reg);
493                 }
494         } else {
495                 /*
496                  * This memory region is not registered.  It could be because of
497                  * a double free or the memory block was not allocated by the
498                  * malloc debug code.
499                  */
500                 astmm_log("WARNING: Freeing unregistered memory %p by %s %s() line %d\n",
501                         ptr, file, func, lineno);
502                 my_do_crash();
503         }
504 }
505
506 void *__ast_repl_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
507 {
508         void *ptr;
509
510         ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 0);
511         if (ptr) {
512                 memset(ptr, 0, size * nmemb);
513         }
514
515         return ptr;
516 }
517
518 static void *__ast_repl_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
519 {
520         void *ptr;
521
522         ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 1);
523         if (ptr) {
524                 memset(ptr, 0, size * nmemb);
525         }
526
527         return ptr;
528 }
529
530 void *__ast_repl_malloc(size_t size, const char *file, int lineno, const char *func)
531 {
532         void *ptr;
533
534         ptr = __ast_alloc_region(size, FUNC_MALLOC, file, lineno, func, 0);
535         if (ptr) {
536                 /* Make sure that the malloced memory is not zero. */
537                 memset(ptr, MALLOC_FILLER, size);
538         }
539
540         return ptr;
541 }
542
543 /*!
544  * \note reglock must be locked before calling.
545  */
546 static struct ast_region *region_find(void *ptr)
547 {
548         int hash;
549         struct ast_region *reg;
550
551         hash = HASH(ptr);
552         for (reg = regions[hash]; reg; reg = AST_LIST_NEXT(reg, node)) {
553                 if (reg->data == ptr) {
554                         break;
555                 }
556         }
557
558         return reg;
559 }
560
561 void *__ast_repl_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func)
562 {
563         size_t len;
564         struct ast_region *found;
565         void *new_mem;
566
567         if (ptr) {
568                 ast_mutex_lock(&reglock);
569                 found = region_find(ptr);
570                 if (!found) {
571                         ast_mutex_unlock(&reglock);
572                         astmm_log("WARNING: Realloc of unregistered memory %p by %s %s() line %d\n",
573                                 ptr, file, func, lineno);
574                         my_do_crash();
575                         return NULL;
576                 }
577                 len = found->len;
578                 ast_mutex_unlock(&reglock);
579         } else {
580                 found = NULL;
581                 len = 0;
582         }
583
584         if (!size) {
585                 __ast_free(ptr, file, lineno, func);
586                 return NULL;
587         }
588
589         new_mem = __ast_alloc_region(size, FUNC_REALLOC, file, lineno, func, 0);
590         if (new_mem) {
591                 if (found) {
592                         /* Copy the old data to the new malloced memory. */
593                         if (size <= len) {
594                                 memcpy(new_mem, ptr, size);
595                         } else {
596                                 memcpy(new_mem, ptr, len);
597                                 /* Make sure that the added memory is not zero. */
598                                 memset(new_mem + len, MALLOC_FILLER, size - len);
599                         }
600                         __ast_free(ptr, file, lineno, func);
601                 } else {
602                         /* Make sure that the malloced memory is not zero. */
603                         memset(new_mem, MALLOC_FILLER, size);
604                 }
605         }
606
607         return new_mem;
608 }
609
610 char *__ast_repl_strdup(const char *s, const char *file, int lineno, const char *func)
611 {
612         size_t len;
613         void *ptr;
614
615         len = strlen(s) + 1;
616         if ((ptr = __ast_alloc_region(len, FUNC_STRDUP, file, lineno, func, 0))) {
617                 strcpy(ptr, s);
618         }
619
620         return ptr;
621 }
622
623 char *__ast_repl_strndup(const char *s, size_t n, const char *file, int lineno, const char *func)
624 {
625         size_t len;
626         char *ptr;
627
628         len = strnlen(s, n);
629         if ((ptr = __ast_alloc_region(len + 1, FUNC_STRNDUP, file, lineno, func, 0))) {
630                 memcpy(ptr, s, len);
631                 ptr[len] = '\0';
632         }
633
634         return ptr;
635 }
636
637 int __ast_repl_asprintf(const char *file, int lineno, const char *func, char **strp, const char *fmt, ...)
638 {
639         int size;
640         va_list ap, ap2;
641         char s;
642         void *ptr;
643
644         va_start(ap, fmt);
645         va_copy(ap2, ap);
646         size = vsnprintf(&s, 1, fmt, ap2);
647         va_end(ap2);
648         ptr = __ast_alloc_region(size + 1, FUNC_ASPRINTF, file, lineno, func, 0);
649         if (!ptr) {
650                 /* As with stdlib *strp is undefined if allocation fails. */
651                 va_end(ap);
652                 return -1;
653         }
654         vsnprintf(ptr, size + 1, fmt, ap);
655         va_end(ap);
656         *strp = ptr;
657
658         return size;
659 }
660
661 int __ast_repl_vasprintf(char **strp, const char *fmt, va_list ap, const char *file, int lineno, const char *func)
662 {
663         int size;
664         va_list ap2;
665         char s;
666         void *ptr;
667
668         va_copy(ap2, ap);
669         size = vsnprintf(&s, 1, fmt, ap2);
670         va_end(ap2);
671         ptr = __ast_alloc_region(size + 1, FUNC_VASPRINTF, file, lineno, func, 0);
672         if (!ptr) {
673                 /* As with stdlib *strp is undefined if allocation fails. */
674                 return -1;
675         }
676         vsnprintf(ptr, size + 1, fmt, ap);
677         *strp = ptr;
678
679         return size;
680 }
681
682 /*!
683  * \internal
684  * \brief Count the number of bytes in the specified freed region.
685  *
686  * \param freed Already freed region blocks storage.
687  *
688  * \note reglock must be locked before calling.
689  *
690  * \return Number of bytes in freed region.
691  */
692 static size_t freed_regions_size(struct ast_freed_regions *freed)
693 {
694         size_t total_len = 0;
695         int idx;
696         struct ast_region *old;
697
698         for (idx = 0; idx < ARRAY_LEN(freed->regions); ++idx) {
699                 old = freed->regions[idx];
700                 if (old) {
701                         total_len += old->len;
702                 }
703         }
704
705         return total_len;
706 }
707
708 static char *handle_memory_atexit_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
709 {
710         switch (cmd) {
711         case CLI_INIT:
712                 e->command = "memory atexit list {on|off}";
713                 e->usage =
714                         "Usage: memory atexit list {on|off}\n"
715                         "       Enable dumping a list of still allocated memory segments at exit.\n";
716                 return NULL;
717         case CLI_GENERATE:
718                 return NULL;
719         }
720
721         if (a->argc != 4) {
722                 return CLI_SHOWUSAGE;
723         }
724
725         if (ast_true(a->argv[3])) {
726                 atexit_list = 1;
727         } else if (ast_false(a->argv[3])) {
728                 atexit_list = 0;
729         } else {
730                 return CLI_SHOWUSAGE;
731         }
732
733         ast_cli(a->fd, "The atexit list is: %s\n", atexit_list ? "On" : "Off");
734
735         return CLI_SUCCESS;
736 }
737
738 static char *handle_memory_atexit_summary(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
739 {
740         char buf[80];
741
742         switch (cmd) {
743         case CLI_INIT:
744                 e->command = "memory atexit summary {off|byline|byfunc|byfile}";
745                 e->usage =
746                         "Usage: memory atexit summary {off|byline|byfunc|byfile}\n"
747                         "       Summary of still allocated memory segments at exit options.\n"
748                         "       off - Disable at exit summary.\n"
749                         "       byline - Enable at exit summary by file line number.\n"
750                         "       byfunc - Enable at exit summary by function name.\n"
751                         "       byfile - Enable at exit summary by file.\n"
752                         "\n"
753                         "       Note: byline, byfunc, and byfile are cumulative enables.\n";
754                 return NULL;
755         case CLI_GENERATE:
756                 return NULL;
757         }
758
759         if (a->argc != 4) {
760                 return CLI_SHOWUSAGE;
761         }
762
763         if (ast_false(a->argv[3])) {
764                 atexit_summary = SUMMARY_OFF;
765         } else if (!strcasecmp(a->argv[3], "byline")) {
766                 atexit_summary |= SUMMARY_BY_LINE;
767         } else if (!strcasecmp(a->argv[3], "byfunc")) {
768                 atexit_summary |= SUMMARY_BY_FUNC;
769         } else if (!strcasecmp(a->argv[3], "byfile")) {
770                 atexit_summary |= SUMMARY_BY_FILE;
771         } else {
772                 return CLI_SHOWUSAGE;
773         }
774
775         if (atexit_summary) {
776                 buf[0] = '\0';
777                 if (atexit_summary & SUMMARY_BY_LINE) {
778                         strcat(buf, "byline");
779                 }
780                 if (atexit_summary & SUMMARY_BY_FUNC) {
781                         if (buf[0]) {
782                                 strcat(buf, " | ");
783                         }
784                         strcat(buf, "byfunc");
785                 }
786                 if (atexit_summary & SUMMARY_BY_FILE) {
787                         if (buf[0]) {
788                                 strcat(buf, " | ");
789                         }
790                         strcat(buf, "byfile");
791                 }
792         } else {
793                 strcpy(buf, "Off");
794         }
795         ast_cli(a->fd, "The atexit summary is: %s\n", buf);
796
797         return CLI_SUCCESS;
798 }
799
800 /*!
801  * \internal
802  * \brief Common summary output at the end of the memory show commands.
803  *
804  * \param fd CLI output file descriptor.
805  * \param whales_len Accumulated size of free large allocations.
806  * \param minnows_len Accumulated size of free small allocations.
807  * \param total_len Accumulated size of all current allocations.
808  * \param selected_len Accumulated size of the selected allocations.
809  * \param cache_len Accumulated size of the allocations that are part of a cache.
810  * \param count Number of selected allocations.
811  *
812  * \return Nothing
813  */
814 static void print_memory_show_common_stats(int fd,
815         unsigned int whales_len,
816         unsigned int minnows_len,
817         unsigned int total_len,
818         unsigned int selected_len,
819         unsigned int cache_len,
820         unsigned int count)
821 {
822         if (cache_len) {
823                 ast_cli(fd, "%10u bytes allocated (%u in caches) in %u selected allocations\n\n",
824                         selected_len, cache_len, count);
825         } else {
826                 ast_cli(fd, "%10u bytes allocated in %u selected allocations\n\n",
827                         selected_len, count);
828         }
829
830         ast_cli(fd, "%10u bytes in all allocations\n", total_len);
831         ast_cli(fd, "%10u bytes in deferred free large allocations\n", whales_len);
832         ast_cli(fd, "%10u bytes in deferred free small allocations\n", minnows_len);
833         ast_cli(fd, "%10u bytes in deferred free allocations\n",
834                 whales_len + minnows_len);
835         ast_cli(fd, "%10u bytes in all allocations and deferred free allocations\n",
836                 total_len + whales_len + minnows_len);
837 }
838
839 static char *handle_memory_show_allocations(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
840 {
841         const char *fn = NULL;
842         struct ast_region *reg;
843         unsigned int idx;
844         unsigned int whales_len;
845         unsigned int minnows_len;
846         unsigned int total_len = 0;
847         unsigned int selected_len = 0;
848         unsigned int cache_len = 0;
849         unsigned int count = 0;
850
851         switch (cmd) {
852         case CLI_INIT:
853                 e->command = "memory show allocations";
854                 e->usage =
855                         "Usage: memory show allocations [<file>|anomalies]\n"
856                         "       Dumps a list of segments of allocated memory.\n"
857                         "       Defaults to listing all memory allocations.\n"
858                         "       <file> - Restricts output to memory allocated by the file.\n"
859                         "       anomalies - Only check for fence violations.\n";
860                 return NULL;
861         case CLI_GENERATE:
862                 return NULL;
863         }
864
865         if (a->argc == 4) {
866                 fn = a->argv[3];
867         } else if (a->argc != 3) {
868                 return CLI_SHOWUSAGE;
869         }
870
871         /* Look for historical misspelled option as well. */
872         if (fn && (!strcasecmp(fn, "anomalies") || !strcasecmp(fn, "anomolies"))) {
873                 regions_check_all_fences();
874                 ast_cli(a->fd, "Anomaly check complete.\n");
875                 return CLI_SUCCESS;
876         }
877
878         ast_mutex_lock(&reglock);
879         for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
880                 for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) {
881                         total_len += reg->len;
882                         if (fn && strcasecmp(fn, reg->file)) {
883                                 continue;
884                         }
885
886                         region_check_fences(reg);
887
888                         ast_cli(a->fd, "%10u bytes allocated%s by %20s() line %5u of %s\n",
889                                 (unsigned int) reg->len, reg->cache ? " (cache)" : "",
890                                 reg->func, reg->lineno, reg->file);
891                         if (reg->bt && !ast_strlen_zero(fn)) {
892                                 print_backtrace(reg->bt, a);
893                         }
894
895                         selected_len += reg->len;
896                         if (reg->cache) {
897                                 cache_len += reg->len;
898                         }
899                         ++count;
900                 }
901         }
902
903         whales_len = freed_regions_size(&whales);
904         minnows_len = freed_regions_size(&minnows);
905         ast_mutex_unlock(&reglock);
906
907         print_memory_show_common_stats(a->fd,
908                 whales_len, minnows_len, total_len,
909                 selected_len, cache_len, count);
910
911         return CLI_SUCCESS;
912 }
913
914 static char *handle_memory_show_summary(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
915 {
916 #define my_max(a, b) ((a) >= (b) ? (a) : (b))
917
918         const char *fn = NULL;
919         int idx;
920         int cmp;
921         struct ast_region *reg;
922         unsigned int whales_len;
923         unsigned int minnows_len;
924         unsigned int total_len = 0;
925         unsigned int selected_len = 0;
926         unsigned int cache_len = 0;
927         unsigned int count = 0;
928         struct file_summary {
929                 struct file_summary *next;
930                 unsigned int len;
931                 unsigned int cache_len;
932                 unsigned int count;
933                 unsigned int lineno;
934                 char name[my_max(sizeof(reg->file), sizeof(reg->func))];
935         } *list = NULL, *cur, **prev;
936
937         switch (cmd) {
938         case CLI_INIT:
939                 e->command = "memory show summary";
940                 e->usage =
941                         "Usage: memory show summary [<file>]\n"
942                         "       Summarizes heap memory allocations by file, or optionally\n"
943                         "       by line if a file is specified.\n";
944                 return NULL;
945         case CLI_GENERATE:
946                 return NULL;
947         }
948
949         if (a->argc == 4) {
950                 fn = a->argv[3];
951         } else if (a->argc != 3) {
952                 return CLI_SHOWUSAGE;
953         }
954
955         ast_mutex_lock(&reglock);
956         for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
957                 for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) {
958                         total_len += reg->len;
959                         if (fn) {
960                                 if (strcasecmp(fn, reg->file)) {
961                                         continue;
962                                 }
963
964                                 /* Sort list by func/lineno.  Find existing or place to insert. */
965                                 for (prev = &list; (cur = *prev); prev = &cur->next) {
966                                         cmp = strcmp(cur->name, reg->func);
967                                         if (cmp < 0) {
968                                                 continue;
969                                         }
970                                         if (cmp > 0) {
971                                                 /* Insert before current */
972                                                 cur = NULL;
973                                                 break;
974                                         }
975                                         cmp = cur->lineno - reg->lineno;
976                                         if (cmp < 0) {
977                                                 continue;
978                                         }
979                                         if (cmp > 0) {
980                                                 /* Insert before current */
981                                                 cur = NULL;
982                                         }
983                                         break;
984                                 }
985                         } else {
986                                 /* Sort list by filename.  Find existing or place to insert. */
987                                 for (prev = &list; (cur = *prev); prev = &cur->next) {
988                                         cmp = strcmp(cur->name, reg->file);
989                                         if (cmp < 0) {
990                                                 continue;
991                                         }
992                                         if (cmp > 0) {
993                                                 /* Insert before current */
994                                                 cur = NULL;
995                                         }
996                                         break;
997                                 }
998                         }
999
1000                         if (!cur) {
1001                                 cur = ast_alloca(sizeof(*cur));
1002                                 memset(cur, 0, sizeof(*cur));
1003                                 cur->lineno = reg->lineno;
1004                                 ast_copy_string(cur->name, fn ? reg->func : reg->file, sizeof(cur->name));
1005
1006                                 cur->next = *prev;
1007                                 *prev = cur;
1008                         }
1009
1010                         cur->len += reg->len;
1011                         if (reg->cache) {
1012                                 cur->cache_len += reg->len;
1013                         }
1014                         ++cur->count;
1015                 }
1016         }
1017
1018         whales_len = freed_regions_size(&whales);
1019         minnows_len = freed_regions_size(&minnows);
1020         ast_mutex_unlock(&reglock);
1021
1022         /* Dump the whole list */
1023         for (cur = list; cur; cur = cur->next) {
1024                 selected_len += cur->len;
1025                 cache_len += cur->cache_len;
1026                 count += cur->count;
1027                 if (cur->cache_len) {
1028                         if (fn) {
1029                                 ast_cli(a->fd, "%10u bytes (%10u cache) in %10u allocations by %20s() line %5u of %s\n",
1030                                         cur->len, cur->cache_len, cur->count, cur->name, cur->lineno, fn);
1031                         } else {
1032                                 ast_cli(a->fd, "%10u bytes (%10u cache) in %10u allocations in file %s\n",
1033                                         cur->len, cur->cache_len, cur->count, cur->name);
1034                         }
1035                 } else {
1036                         if (fn) {
1037                                 ast_cli(a->fd, "%10u bytes in %10u allocations by %20s() line %5u of %s\n",
1038                                         cur->len, cur->count, cur->name, cur->lineno, fn);
1039                         } else {
1040                                 ast_cli(a->fd, "%10u bytes in %10u allocations in file %s\n",
1041                                         cur->len, cur->count, cur->name);
1042                         }
1043                 }
1044         }
1045
1046         print_memory_show_common_stats(a->fd,
1047                 whales_len, minnows_len, total_len,
1048                 selected_len, cache_len, count);
1049
1050         return CLI_SUCCESS;
1051 }
1052
1053 static char *handle_memory_backtrace(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1054 {
1055         switch (cmd) {
1056         case CLI_INIT:
1057                 e->command = "memory backtrace {on|off}";
1058                 e->usage =
1059                         "Usage: memory backtrace {on|off}\n"
1060                         "       Enable dumping an allocation backtrace with memory diagnostics.\n"
1061                         "       Note that saving the backtrace data for each allocation\n"
1062                         "       can be CPU intensive.\n";
1063                 return NULL;
1064         case CLI_GENERATE:
1065                 return NULL;
1066         }
1067
1068         if (a->argc != 3) {
1069                 return CLI_SHOWUSAGE;
1070         }
1071
1072         if (ast_true(a->argv[2])) {
1073                 backtrace_enabled = 1;
1074         } else if (ast_false(a->argv[2])) {
1075                 backtrace_enabled = 0;
1076         } else {
1077                 return CLI_SHOWUSAGE;
1078         }
1079
1080         ast_cli(a->fd, "The memory backtrace is: %s\n", backtrace_enabled ? "On" : "Off");
1081
1082         return CLI_SUCCESS;
1083 }
1084
1085 static struct ast_cli_entry cli_memory[] = {
1086         AST_CLI_DEFINE(handle_memory_atexit_list, "Enable memory allocations not freed at exit list."),
1087         AST_CLI_DEFINE(handle_memory_atexit_summary, "Enable memory allocations not freed at exit summary."),
1088         AST_CLI_DEFINE(handle_memory_show_allocations, "Display outstanding memory allocations"),
1089         AST_CLI_DEFINE(handle_memory_show_summary, "Summarize outstanding memory allocations"),
1090         AST_CLI_DEFINE(handle_memory_backtrace, "Enable dumping an allocation backtrace with memory diagnostics."),
1091 };
1092
1093 AST_LIST_HEAD_NOLOCK(region_list, ast_region);
1094
1095 /*!
1096  * \internal
1097  * \brief Convert the allocated regions hash table to a list.
1098  *
1099  * \param list Fill list with the allocated regions.
1100  *
1101  * \details
1102  * Take all allocated regions from the regions[] and put them
1103  * into the list.
1104  *
1105  * \note reglock must be locked before calling.
1106  *
1107  * \note This function is destructive to the regions[] lists.
1108  *
1109  * \return Length of list created.
1110  */
1111 static size_t mm_atexit_hash_list(struct region_list *list)
1112 {
1113         struct ast_region *reg;
1114         size_t total_length;
1115         int idx;
1116
1117         total_length = 0;
1118         for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
1119                 while ((reg = regions[idx])) {
1120                         regions[idx] = AST_LIST_NEXT(reg, node);
1121                         AST_LIST_NEXT(reg, node) = NULL;
1122                         AST_LIST_INSERT_HEAD(list, reg, node);
1123                         ++total_length;
1124                 }
1125         }
1126         return total_length;
1127 }
1128
1129 /*!
1130  * \internal
1131  * \brief Put the regions list into the allocated regions hash table.
1132  *
1133  * \param list List to put into the allocated regions hash table.
1134  *
1135  * \note reglock must be locked before calling.
1136  *
1137  * \return Nothing
1138  */
1139 static void mm_atexit_hash_restore(struct region_list *list)
1140 {
1141         struct ast_region *reg;
1142         int hash;
1143
1144         while ((reg = AST_LIST_REMOVE_HEAD(list, node))) {
1145                 hash = HASH(reg->data);
1146                 AST_LIST_NEXT(reg, node) = regions[hash];
1147                 regions[hash] = reg;
1148         }
1149 }
1150
1151 /*!
1152  * \internal
1153  * \brief Sort regions comparision.
1154  *
1155  * \param left Region to compare.
1156  * \param right Region to compare.
1157  *
1158  * \retval <0 if left < right
1159  * \retval =0 if left == right
1160  * \retval >0 if left > right
1161  */
1162 static int mm_atexit_cmp(struct ast_region *left, struct ast_region *right)
1163 {
1164         int cmp;
1165         ptrdiff_t cmp_ptr;
1166         ssize_t cmp_size;
1167
1168         /* Sort by filename. */
1169         cmp = strcmp(left->file, right->file);
1170         if (cmp) {
1171                 return cmp;
1172         }
1173
1174         /* Sort by line number. */
1175         cmp = left->lineno - right->lineno;
1176         if (cmp) {
1177                 return cmp;
1178         }
1179
1180         /* Sort by allocated size. */
1181         cmp_size = left->len - right->len;
1182         if (cmp_size) {
1183                 if (cmp_size < 0) {
1184                         return -1;
1185                 }
1186                 return 1;
1187         }
1188
1189         /* Sort by allocated pointers just because. */
1190         cmp_ptr = left->data - right->data;
1191         if (cmp_ptr) {
1192                 if (cmp_ptr < 0) {
1193                         return -1;
1194                 }
1195                 return 1;
1196         }
1197
1198         return 0;
1199 }
1200
1201 /*!
1202  * \internal
1203  * \brief Merge the given sorted sublists into sorted order onto the end of the list.
1204  *
1205  * \param list Merge sublists onto this list.
1206  * \param sub1 First sublist to merge.
1207  * \param sub2 Second sublist to merge.
1208  *
1209  * \return Nothing
1210  */
1211 static void mm_atexit_list_merge(struct region_list *list, struct region_list *sub1, struct region_list *sub2)
1212 {
1213         struct ast_region *reg;
1214
1215         for (;;) {
1216                 if (AST_LIST_EMPTY(sub1)) {
1217                         /* The remaining sublist goes onto the list. */
1218                         AST_LIST_APPEND_LIST(list, sub2, node);
1219                         break;
1220                 }
1221                 if (AST_LIST_EMPTY(sub2)) {
1222                         /* The remaining sublist goes onto the list. */
1223                         AST_LIST_APPEND_LIST(list, sub1, node);
1224                         break;
1225                 }
1226
1227                 if (mm_atexit_cmp(AST_LIST_FIRST(sub1), AST_LIST_FIRST(sub2)) <= 0) {
1228                         reg = AST_LIST_REMOVE_HEAD(sub1, node);
1229                 } else {
1230                         reg = AST_LIST_REMOVE_HEAD(sub2, node);
1231                 }
1232                 AST_LIST_INSERT_TAIL(list, reg, node);
1233         }
1234 }
1235
1236 /*!
1237  * \internal
1238  * \brief Take sublists off of the given list.
1239  *
1240  * \param list Source list to remove sublists from the beginning of list.
1241  * \param sub Array of sublists to fill. (Lists are empty on entry.)
1242  * \param num_lists Number of lists to remove from the source list.
1243  * \param size Size of the sublists to remove.
1244  * \param remaining Remaining number of elements on the source list.
1245  *
1246  * \return Nothing
1247  */
1248 static void mm_atexit_list_split(struct region_list *list, struct region_list sub[], size_t num_lists, size_t size, size_t *remaining)
1249 {
1250         int idx;
1251
1252         for (idx = 0; idx < num_lists; ++idx) {
1253                 size_t count;
1254
1255                 if (*remaining < size) {
1256                         /* The remaining source list goes onto the sublist. */
1257                         AST_LIST_APPEND_LIST(&sub[idx], list, node);
1258                         *remaining = 0;
1259                         break;
1260                 }
1261
1262                 /* Take a sublist off the beginning of the source list. */
1263                 *remaining -= size;
1264                 for (count = size; count--;) {
1265                         struct ast_region *reg;
1266
1267                         reg = AST_LIST_REMOVE_HEAD(list, node);
1268                         AST_LIST_INSERT_TAIL(&sub[idx], reg, node);
1269                 }
1270         }
1271 }
1272
1273 /*!
1274  * \internal
1275  * \brief Sort the regions list using mergesort.
1276  *
1277  * \param list Allocated regions list to sort.
1278  * \param length Length of the list.
1279  *
1280  * \return Nothing
1281  */
1282 static void mm_atexit_list_sort(struct region_list *list, size_t length)
1283 {
1284         /*! Semi-sorted merged list. */
1285         struct region_list merged = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
1286         /*! Sublists to merge. (Can only merge two sublists at this time.) */
1287         struct region_list sub[2] = {
1288                 AST_LIST_HEAD_NOLOCK_INIT_VALUE,
1289                 AST_LIST_HEAD_NOLOCK_INIT_VALUE
1290         };
1291         /*! Sublist size. */
1292         size_t size = 1;
1293         /*! Remaining elements in the list. */
1294         size_t remaining;
1295         /*! Number of sublist merge passes to process the list. */
1296         int passes;
1297
1298         for (;;) {
1299                 remaining = length;
1300
1301                 passes = 0;
1302                 while (!AST_LIST_EMPTY(list)) {
1303                         mm_atexit_list_split(list, sub, ARRAY_LEN(sub), size, &remaining);
1304                         mm_atexit_list_merge(&merged, &sub[0], &sub[1]);
1305                         ++passes;
1306                 }
1307                 AST_LIST_APPEND_LIST(list, &merged, node);
1308                 if (passes <= 1) {
1309                         /* The list is now sorted. */
1310                         break;
1311                 }
1312
1313                 /* Double the sublist size to remove for next round. */
1314                 size <<= 1;
1315         }
1316 }
1317
1318 /*!
1319  * \internal
1320  * \brief List all regions currently allocated.
1321  *
1322  * \param alloced regions list.
1323  *
1324  * \return Nothing
1325  */
1326 static void mm_atexit_regions_list(struct region_list *alloced)
1327 {
1328         struct ast_region *reg;
1329
1330         AST_LIST_TRAVERSE(alloced, reg, node) {
1331                 astmm_log("%s %s() line %u: %u bytes%s at %p\n",
1332                         reg->file, reg->func, reg->lineno,
1333                         (unsigned int) reg->len, reg->cache ? " (cache)" : "", reg->data);
1334         }
1335 }
1336
1337 /*!
1338  * \internal
1339  * \brief Summarize all regions currently allocated.
1340  *
1341  * \param alloced Sorted regions list.
1342  *
1343  * \return Nothing
1344  */
1345 static void mm_atexit_regions_summary(struct region_list *alloced)
1346 {
1347         struct ast_region *reg;
1348         struct ast_region *next;
1349         struct {
1350                 unsigned int count;
1351                 unsigned int len;
1352                 unsigned int cache_len;
1353         } by_line, by_func, by_file, total;
1354
1355         by_line.count = 0;
1356         by_line.len = 0;
1357         by_line.cache_len = 0;
1358
1359         by_func.count = 0;
1360         by_func.len = 0;
1361         by_func.cache_len = 0;
1362
1363         by_file.count = 0;
1364         by_file.len = 0;
1365         by_file.cache_len = 0;
1366
1367         total.count = 0;
1368         total.len = 0;
1369         total.cache_len = 0;
1370
1371         AST_LIST_TRAVERSE(alloced, reg, node) {
1372                 next = AST_LIST_NEXT(reg, node);
1373
1374                 ++by_line.count;
1375                 by_line.len += reg->len;
1376                 if (reg->cache) {
1377                         by_line.cache_len += reg->len;
1378                 }
1379                 if (next && !strcmp(reg->file, next->file) && reg->lineno == next->lineno) {
1380                         continue;
1381                 }
1382                 if (atexit_summary & SUMMARY_BY_LINE) {
1383                         if (by_line.cache_len) {
1384                                 astmm_log("%10u bytes (%u in caches) in %u allocations. %s %s() line %u\n",
1385                                         by_line.len, by_line.cache_len, by_line.count, reg->file, reg->func, reg->lineno);
1386                         } else {
1387                                 astmm_log("%10u bytes in %5u allocations. %s %s() line %u\n",
1388                                         by_line.len, by_line.count, reg->file, reg->func, reg->lineno);
1389                         }
1390                 }
1391
1392                 by_func.count += by_line.count;
1393                 by_func.len += by_line.len;
1394                 by_func.cache_len += by_line.cache_len;
1395                 by_line.count = 0;
1396                 by_line.len = 0;
1397                 by_line.cache_len = 0;
1398                 if (next && !strcmp(reg->file, next->file) && !strcmp(reg->func, next->func)) {
1399                         continue;
1400                 }
1401                 if (atexit_summary & SUMMARY_BY_FUNC) {
1402                         if (by_func.cache_len) {
1403                                 astmm_log("%10u bytes (%u in caches) in %u allocations. %s %s()\n",
1404                                         by_func.len, by_func.cache_len, by_func.count, reg->file, reg->func);
1405                         } else {
1406                                 astmm_log("%10u bytes in %5u allocations. %s %s()\n",
1407                                         by_func.len, by_func.count, reg->file, reg->func);
1408                         }
1409                 }
1410
1411                 by_file.count += by_func.count;
1412                 by_file.len += by_func.len;
1413                 by_file.cache_len += by_func.cache_len;
1414                 by_func.count = 0;
1415                 by_func.len = 0;
1416                 by_func.cache_len = 0;
1417                 if (next && !strcmp(reg->file, next->file)) {
1418                         continue;
1419                 }
1420                 if (atexit_summary & SUMMARY_BY_FILE) {
1421                         if (by_file.cache_len) {
1422                                 astmm_log("%10u bytes (%u in caches) in %u allocations. %s\n",
1423                                         by_file.len, by_file.cache_len, by_file.count, reg->file);
1424                         } else {
1425                                 astmm_log("%10u bytes in %5u allocations. %s\n",
1426                                         by_file.len, by_file.count, reg->file);
1427                         }
1428                 }
1429
1430                 total.count += by_file.count;
1431                 total.len += by_file.len;
1432                 total.cache_len += by_file.cache_len;
1433                 by_file.count = 0;
1434                 by_file.len = 0;
1435                 by_file.cache_len = 0;
1436         }
1437
1438         if (total.cache_len) {
1439                 astmm_log("%u bytes (%u in caches) in %u allocations.\n",
1440                         total.len, total.cache_len, total.count);
1441         } else {
1442                 astmm_log("%u bytes in %u allocations.\n", total.len, total.count);
1443         }
1444 }
1445
1446 /*!
1447  * \internal
1448  * \brief Dump the memory allocations atexit.
1449  *
1450  * \note reglock must be locked before calling.
1451  *
1452  * \return Nothing
1453  */
1454 static void mm_atexit_dump(void)
1455 {
1456         struct region_list alloced_atexit = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
1457         size_t length;
1458
1459         length = mm_atexit_hash_list(&alloced_atexit);
1460         if (!length) {
1461                 /* Wow!  This is amazing! */
1462                 astmm_log("Exiting with all memory freed.\n");
1463                 return;
1464         }
1465
1466         mm_atexit_list_sort(&alloced_atexit, length);
1467
1468         astmm_log("Exiting with the following memory not freed:\n");
1469         if (atexit_list) {
1470                 mm_atexit_regions_list(&alloced_atexit);
1471         }
1472         if (atexit_summary) {
1473                 mm_atexit_regions_summary(&alloced_atexit);
1474         }
1475
1476         /*
1477          * Put the alloced list back into regions[].
1478          *
1479          * We have do this because we can get called before all other
1480          * threads have terminated.
1481          */
1482         mm_atexit_hash_restore(&alloced_atexit);
1483 }
1484
1485 /*!
1486  * \internal
1487  * \return Nothing
1488  */
1489 static void mm_atexit_final(void)
1490 {
1491         FILE *log;
1492
1493         /* Only wait if we want atexit allocation dumps. */
1494         if (atexit_list || atexit_summary) {
1495                 fprintf(stderr, "Waiting 10 seconds to let other threads die.\n");
1496                 sleep(10);
1497         }
1498
1499         regions_check_all_fences();
1500
1501         /* Flush all delayed memory free circular arrays. */
1502         freed_regions_flush(&whales);
1503         freed_regions_flush(&minnows);
1504
1505         /* Peform atexit allocation dumps. */
1506         if (atexit_list || atexit_summary) {
1507                 ast_mutex_lock(&reglock);
1508                 mm_atexit_dump();
1509                 ast_mutex_unlock(&reglock);
1510         }
1511
1512         /* Close the log file. */
1513         log = mmlog;
1514         mmlog = NULL;
1515         if (log) {
1516                 fclose(log);
1517         }
1518 }
1519
1520 void load_astmm_phase_1(void)
1521 {
1522         atexit(mm_atexit_final);
1523 }
1524
1525 /*!
1526  * \internal
1527  * \return Nothing
1528  */
1529 static void mm_atexit_ast(void)
1530 {
1531         ast_cli_unregister_multiple(cli_memory, ARRAY_LEN(cli_memory));
1532 }
1533
1534 void load_astmm_phase_2(void)
1535 {
1536         char filename[PATH_MAX];
1537
1538         ast_cli_register_multiple(cli_memory, ARRAY_LEN(cli_memory));
1539
1540         snprintf(filename, sizeof(filename), "%s/mmlog", ast_config_AST_LOG_DIR);
1541
1542         ast_verb(1, "Asterisk Malloc Debugger Started (see %s))\n", filename);
1543
1544         mmlog = fopen(filename, "a+");
1545         if (mmlog) {
1546                 fprintf(mmlog, "%ld - New session\n", (long) time(NULL));
1547                 fflush(mmlog);
1548         } else {
1549                 ast_log(LOG_ERROR, "Could not open malloc debug log file: %s\n", filename);
1550         }
1551
1552         ast_register_cleanup(mm_atexit_ast);
1553 }
1554
1555 #else   /* !defined(__AST_DEBUG_MALLOC) */
1556
1557 void load_astmm_phase_1(void)
1558 {
1559 }
1560
1561 void load_astmm_phase_2(void)
1562 {
1563 }
1564
1565 void *__ast_repl_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
1566 {
1567         DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
1568
1569         return calloc(nmemb, size);
1570 }
1571
1572 static void *__ast_repl_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
1573 {
1574         DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
1575
1576         return calloc(nmemb, size);
1577 }
1578
1579 void *__ast_repl_malloc(size_t size, const char *file, int lineno, const char *func)
1580 {
1581         DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
1582
1583         return malloc(size);
1584 }
1585
1586 void __ast_free(void *ptr, const char *file, int lineno, const char *func)
1587 {
1588         free(ptr);
1589 }
1590
1591 void *__ast_repl_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func)
1592 {
1593         DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
1594
1595         return realloc(ptr, size);
1596 }
1597
1598 char *__ast_repl_strdup(const char *s, const char *file, int lineno, const char *func)
1599 {
1600         DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
1601
1602         return strdup(s);
1603 }
1604
1605 char *__ast_repl_strndup(const char *s, size_t n, const char *file, int lineno, const char *func)
1606 {
1607         DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, NULL);
1608
1609         return strndup(s, n);
1610 }
1611
1612 int __ast_repl_asprintf(const char *file, int lineno, const char *func, char **strp, const char *format, ...)
1613 {
1614         int res;
1615         va_list ap;
1616
1617         DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, -1);
1618
1619         va_start(ap, format);
1620         res = vasprintf(strp, format, ap);
1621         va_end(ap);
1622
1623         return res;
1624 }
1625
1626 int __ast_repl_vasprintf(char **strp, const char *format, va_list ap, const char *file, int lineno, const char *func)
1627 {
1628         DEBUG_CHAOS_RETURN(DEBUG_CHAOS_ALLOC_CHANCE, -1);
1629
1630         return vasprintf(strp, format, ap);
1631 }
1632
1633 #endif  /* defined(__AST_DEBUG_MALLOC) */
1634
1635 void *__ast_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
1636 {
1637         void *p;
1638
1639         p = __ast_repl_calloc(nmemb, size, file, lineno, func);
1640         if (!p) {
1641                 MALLOC_FAILURE_MSG;
1642         }
1643
1644         return p;
1645 }
1646
1647 void *__ast_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
1648 {
1649         void *p;
1650
1651         p = __ast_repl_calloc_cache(nmemb, size, file, lineno, func);
1652         if (!p) {
1653                 MALLOC_FAILURE_MSG;
1654         }
1655
1656         return p;
1657
1658 }
1659
1660 void *__ast_malloc(size_t size, const char *file, int lineno, const char *func)
1661 {
1662         void *p;
1663
1664         p = __ast_repl_malloc(size, file, lineno, func);
1665         if (!p) {
1666                 MALLOC_FAILURE_MSG;
1667         }
1668
1669         return p;
1670 }
1671
1672 void *__ast_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func)
1673 {
1674         void *newp;
1675
1676         newp = __ast_repl_realloc(ptr, size, file, lineno, func);
1677         if (!newp) {
1678                 MALLOC_FAILURE_MSG;
1679         }
1680
1681         return newp;
1682 }
1683
1684 char *__ast_strdup(const char *s, const char *file, int lineno, const char *func)
1685 {
1686         char *newstr = NULL;
1687
1688         if (s) {
1689                 newstr = __ast_repl_strdup(s, file, lineno, func);
1690                 if (!newstr) {
1691                         MALLOC_FAILURE_MSG;
1692                 }
1693         }
1694
1695         return newstr;
1696 }
1697
1698 char *__ast_strndup(const char *s, size_t n, const char *file, int lineno, const char *func)
1699 {
1700         char *newstr = NULL;
1701
1702         if (s) {
1703                 newstr = __ast_repl_strndup(s, n, file, lineno, func);
1704                 if (!newstr) {
1705                         MALLOC_FAILURE_MSG;
1706                 }
1707         }
1708
1709         return newstr;
1710 }
1711
1712 int __ast_asprintf(const char *file, int lineno, const char *func, char **strp, const char *format, ...)
1713 {
1714         int res;
1715         va_list ap;
1716
1717         va_start(ap, format);
1718         res = __ast_repl_vasprintf(strp, format, ap, file, lineno, func);
1719         if (res < 0) {
1720                 /*
1721                  * *strp is undefined so set to NULL to ensure it is
1722                  * initialized to something useful.
1723                  */
1724                 *strp = NULL;
1725
1726                 MALLOC_FAILURE_MSG;
1727         }
1728         va_end(ap);
1729
1730         return res;
1731 }
1732
1733 int __ast_vasprintf(char **strp, const char *format, va_list ap, const char *file, int lineno, const char *func)
1734 {
1735         int res;
1736
1737         res = __ast_repl_vasprintf(strp, format, ap, file, lineno, func);
1738         if (res < 0) {
1739                 /*
1740                  * *strp is undefined so set to NULL to ensure it is
1741                  * initialized to something useful.
1742                  */
1743                 *strp = NULL;
1744
1745                 MALLOC_FAILURE_MSG;
1746         }
1747
1748         return res;
1749 }
1750
1751 void *ast_std_malloc(size_t size)
1752 {
1753         return malloc(size);
1754 }
1755
1756 void *ast_std_calloc(size_t nmemb, size_t size)
1757 {
1758         return calloc(nmemb, size);
1759 }
1760
1761 void *ast_std_realloc(void *ptr, size_t size)
1762 {
1763         return realloc(ptr, size);
1764 }
1765
1766 void ast_std_free(void *ptr)
1767 {
1768         free(ptr);
1769 }
1770
1771 void ast_free_ptr(void *ptr)
1772 {
1773         ast_free(ptr);
1774 }