From 4f30c7e91fb0ad4c9936336e6acbf1e0f4106dea Mon Sep 17 00:00:00 2001 From: Matthew Jordan Date: Fri, 11 Apr 2014 02:59:19 +0000 Subject: main/astobj2: Make REF_DEBUG a menuselect item; improve REF_DEBUG output This patch does the following: (1) It makes REF_DEBUG a meneselect item. Enabling REF_DEBUG now enables REF_DEBUG globally throughout Asterisk. (2) The ref debug log file is now created in the AST_LOG_DIR directory. Every run will now blow away the previous run (as large ref files sometimes caused issues). We now also no longer open/close the file on each write, instead relying on fflush to make sure data gets written to the file (in case the ao2 call being performed is about to cause a crash) (3) It goes with a comma delineated format for the ref debug file. This makes parsing much easier. This also now includes the thread ID of the thread that caused ref change. (4) A new python script instead for refcounting has been added in the contrib/scripts folder. (5) The old refcounter implementation in utils/ has been removed. Review: https://reviewboard.asterisk.org/r/3377/ ........ Merged revisions 412114 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 412115 from http://svn.asterisk.org/svn/asterisk/branches/11 ........ Merged revisions 412153 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@412154 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- utils/refcounter.c | 317 ----------------------------------------------------- 1 file changed, 317 deletions(-) delete mode 100644 utils/refcounter.c (limited to 'utils/refcounter.c') diff --git a/utils/refcounter.c b/utils/refcounter.c deleted file mode 100644 index 16d7fc8d5..000000000 --- a/utils/refcounter.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Asterisk -- An open source telephony toolkit. - * - * Copyright (C) 2008, Steve Murphy - * - * Steve Murphy - * - * See http://www.asterisk.org for more information about - * the Asterisk project. Please do not directly contact - * any of the maintainers of this project for assistance; - * the project provides a web site, mailing lists and IRC - * channels for your use. - * - * This program is free software, distributed under the terms of - * the GNU General Public License Version 2. See the LICENSE file - * at the top of the source tree. - */ - -/*! \file - * - * \brief A program to read in the /tmp/refs file generated - * by astobj2 code when the REF_DEBUG macro is defined. - * It will read in the file line by line, and - * sort the data out by object, and check to see - * if the refcounts balance to zero, and the object - * was destroyed just once. Any problems that are - * found are reported to stdout and the objects - * ref count history is printed out. If all is well, - * this program reads in the /tmp/refs file and - * generates no output. No news is good news. - * The contents of the /tmp/refs file looks like this: - * \verbatim - * 0x84fd718 -1 astobj2.c:926:cd_cb_debug (deref object via container destroy) [@1] - * 0x84fd718 =1 chan_sip.c:19760:build_user (allocate a user struct) - * 0x84fd718 +1 chan_sip.c:21558:reload_config (link user into users table) [@1] - * 0x84fd718 -1 chan_sip.c:2376:unref_user (Unref the result of build_user. Now, the table link is the only one left.) [@2] - * 0x84fd718 **call destructor** astobj2.c:926:cd_cb_debug (deref object via container destroy) - * \endverbatim - * - * \author Steve Murphy - */ - -/*** MODULEINFO - extended - ***/ - -#include "asterisk.h" -ASTERISK_FILE_VERSION(__FILE__, "$Revision$") - -#include -#include -#include -#include -#include "asterisk/lock.h" -#include "asterisk/hashtab.h" -#include "asterisk/channel.h" -#include "asterisk/utils.h" -#include "asterisk/module.h" - -struct rc_hist -{ - char *desc; - struct rc_hist *next; -}; - -struct rc_obj /* short for refcounted object */ -{ - unsigned int addr; - unsigned int count; /* this plus addr makes each entry unique, starts at 1 */ - int last_count; /* count 1 objects will record how many other objects had the same addr */ - int destroy_count; - int total_refcount; - struct rc_hist *hist; - struct rc_hist *last; -}; - -void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used); -void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used) -{ -} - -static unsigned int hashtab_hash_rc(const void *obj) -{ - const struct rc_obj *rc = obj; - return rc->addr + rc->count; /* it's addr will make a FINE hash */ -} - -static int hashtab_compare_rc(const void *a, const void *b) -{ - const struct rc_obj *rca = a; - const struct rc_obj *rcb = b; - if (rca->addr == rcb->addr && rca->count == rcb->count) - return 0; - else - return 1; -} - - -static struct rc_obj *alloc_obj(unsigned int addr, unsigned int count) -{ - struct rc_obj *x = calloc(1,sizeof(struct rc_obj)); - x->addr = addr; - x->count = count; - x->last_count = 1; - x->total_refcount = 1; - return x; -} - -static void add_to_hist(char *buffer, struct rc_obj *obj) -{ - struct rc_hist *y = calloc(1,sizeof(struct rc_hist)); - y->desc = strdup(buffer); - if (obj->last) { - obj->last->next = y; - obj->last = y; - } else { - obj->hist = obj->last = y; - } -} - - - -int main(int argc,char **argv) -{ - char linebuffer[300]; - FILE *ifile = fopen("/tmp/refs", "r"); - char *t; - unsigned int un; - struct rc_obj *curr_obj, *count1_obj; - struct rc_obj lookup; - struct ast_hashtab_iter *it; - struct ast_hashtab *objhash; - - if (!ifile) { - printf("Sorry, Cannot open /tmp/refs!\n"); - exit(10); - } - - objhash = ast_hashtab_create(9000, hashtab_compare_rc, ast_hashtab_resize_java, ast_hashtab_newsize_java, hashtab_hash_rc, 1); - - while (fgets(linebuffer, sizeof(linebuffer), ifile)) { - /* collect data about the entry */ - un = strtoul(linebuffer, &t, 16); - lookup.addr = un; - lookup.count = 1; - - count1_obj = ast_hashtab_lookup(objhash, &lookup); - - if (count1_obj) { - /* there IS a count1 obj, so let's see which one we REALLY want */ - if (*(t+1) == '=') { - /* start a new object! */ - curr_obj = alloc_obj(un, ++count1_obj->last_count); - /* put it in the hashtable */ - ast_hashtab_insert_safe(objhash, curr_obj); - } else { - if (count1_obj->last_count > 1) { - lookup.count = count1_obj->last_count; - curr_obj = ast_hashtab_lookup(objhash, &lookup); - } else { - curr_obj = count1_obj; - } - - } - - } else { - /* NO obj at ALL? -- better make one! */ - if (*(t+1) != '=') { - printf("BAD: object %x appears without previous allocation marker!\n", un); - } - curr_obj = count1_obj = alloc_obj(un, 1); - /* put it in the hashtable */ - ast_hashtab_insert_safe(objhash, curr_obj); - - } - - if (*(t+1) == '+' || *(t+1) == '-' ) { - curr_obj->total_refcount += strtol(t+1, NULL, 10); - } else if (*(t+1) == '*') { - curr_obj->destroy_count++; - } - - add_to_hist(linebuffer, curr_obj); - } - fclose(ifile); - - /* traverse the objects and check for problems */ - it = ast_hashtab_start_traversal(objhash); - while ((curr_obj = ast_hashtab_next(it))) { - if (curr_obj->total_refcount != 0 || curr_obj->destroy_count != 1) { - struct rc_hist *h; - if (curr_obj->total_refcount != 0) - printf("Problem: net Refcount not zero for object %x\n", curr_obj->addr); - if (curr_obj->destroy_count > 1 ) - printf("Problem: Object %x destroyed more than once!\n", curr_obj->addr); - printf("Object %x history:\n", curr_obj->addr); - for(h=curr_obj->hist;h;h=h->next) { - printf(" %s", h->desc); - } - printf("==============\n"); - } - } - ast_hashtab_end_traversal(it); - return 0; -} - - -/* stub routines to satisfy linking with asterisk subcomponents */ - -#ifndef LOW_MEMORY -int ast_add_profile(const char *x, uint64_t scale) -{ - return 0; -} -#endif - -int ast_loader_register(int (*updater)(void)) -{ - return 1; -} - -int ast_loader_unregister(int (*updater)(void)) -{ - return 1; -} -void ast_module_register(const struct ast_module_info *x) -{ -} - -void ast_module_unregister(const struct ast_module_info *x) -{ -} - -#ifndef LOW_MEMORY -void ast_register_file_version(const char *file, const char *version) -{ -} - -void ast_unregister_file_version(const char *file) -{ - -} - -#undef ast_mark - -int64_t ast_mark(int x, int start1_stop0) -{ - return 0; -} -#endif - -void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...) -{ - va_list vars; - va_start(vars,fmt); - printf("LOG: lev:%d file:%s line:%d func: %s ", - level, file, line, function); - vprintf(fmt, vars); - fflush(stdout); - va_end(vars); -} - -void __ast_verbose(const char *file, int line, const char *func, int level, const char *fmt, ...) -{ - va_list vars; - va_start(vars,fmt); - - printf("VERBOSE: "); - vprintf(fmt, vars); - fflush(stdout); - va_end(vars); -} - -void ast_register_thread(char *name) -{ - -} - -void ast_unregister_thread(void *id) -{ -} -#ifdef HAVE_BKTR -struct ast_bt *__ast_bt_create(void); -struct ast_bt *__ast_bt_create(void) -{ - return NULL; -} - -int __ast_bt_get_addresses(struct ast_bt *bt); -int __ast_bt_get_addresses(struct ast_bt *bt) -{ - return 0; -} - -char **__ast_bt_get_symbols(void **addresses, size_t num_frames); -char **__ast_bt_get_symbols(void **addresses, size_t num_frames) -{ - char **foo = calloc(num_frames, sizeof(char *) + 1); - if (foo) { - int i; - for (i = 0; i < num_frames; i++) { - foo[i] = (char *) foo + sizeof(char *) * num_frames; - } - } - return foo; -} - -void *__ast_bt_destroy(struct ast_bt *bt); -void *__ast_bt_destroy(struct ast_bt *bt) -{ - return NULL; -} - -void ast_log_backtrace(void) -{ -} -#endif -- cgit v1.2.3