From: Amos Jeffries Date: Sun, 21 Nov 2010 11:03:56 +0000 (+1300) Subject: failure_notify is C++-only X-Git-Tag: take1~71 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2ded5176931a7d1f472a39c200747a1f26480f27;p=thirdparty%2Fsquid.git failure_notify is C++-only The global function failure_notify is tightly type dependent. This makes sure all code which uses it is C++ and wraps it away from any situations where the symbol may be re-defined with a C definition. As a side-effect the malloc tracing code is shuffled into its own file. --- diff --git a/compat/compat_shared.h b/compat/compat_shared.h index b4c1260f6a..6e63e635bd 100644 --- a/compat/compat_shared.h +++ b/compat/compat_shared.h @@ -13,17 +13,14 @@ * of the requirements for wrapping your hack for safe portability. */ +#ifdef __cplusplus /* * Define an error display handler override. * If error_notify is set by the linked program it will be used by the local * portability functions. Otherwise perror() will be used. */ -#ifdef __cplusplus -extern "C" -#else -extern +extern void (*failure_notify) (const char *); #endif -void (*failure_notify) (const char *); /* * sys/resource.h and sys/time.h are apparently order-dependant. diff --git a/lib/Makefile.am b/lib/Makefile.am index f30ad06f00..01366d15bc 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -56,6 +56,7 @@ libmisccontainers_la_SOURCES = \ hash.c libmiscutil_la_SOURCES = \ + malloc_trace.cc \ MemPool.cc \ MemPoolChunked.cc \ MemPoolMalloc.cc \ diff --git a/lib/malloc_trace.cc b/lib/malloc_trace.cc new file mode 100644 index 0000000000..fe1224a690 --- /dev/null +++ b/lib/malloc_trace.cc @@ -0,0 +1,426 @@ +/* + * $Id$ + * + * DEBUG: + * AUTHOR: Harvest Derived + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#define _etext etext + +#include "config.h" +#include "profiler/Profiler.h" +#include "util.h" + +#if HAVE_STDIO_H +#include +#endif +#if HAVE_STRING_H +#include +#endif +#if HAVE_CTYPE_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_GNUMALLLOC_H +#include +#elif HAVE_MALLOC_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_MATH_H +#include +#endif +#if HAVE_ASSERT_H +#include +#endif + +#if MEM_GEN_TRACE + +static FILE *tracefp = NULL; + +void +log_trace_init(char *fn) +{ + tracefp = fopen(fn, "a+"); + + if (!tracefp) { + perror("log_trace_init"); + exit(1); + } +} + +void +log_trace_done() +{ + fclose(tracefp); + tracefp = NULL; +} + +#endif + +#if XMALLOC_TRACE +char *xmalloc_file = ""; +int xmalloc_line = 0; +char *xmalloc_func = ""; +static int xmalloc_count = 0; +int xmalloc_trace = 0; /* Enable with -m option */ +size_t xmalloc_total = 0; +#undef xmalloc +#undef xfree +#undef xxfree +#undef xrealloc +#undef xcalloc +#undef xstrdup +#endif + +#if XMALLOC_DEBUG +#define DBG_ARRY_SZ (1<<11) +#define DBG_ARRY_BKTS (1<<8) +static void *(*malloc_ptrs)[DBG_ARRY_SZ]; +static int malloc_size[DBG_ARRY_BKTS][DBG_ARRY_SZ]; +#if XMALLOC_TRACE +static char *malloc_file[DBG_ARRY_BKTS][DBG_ARRY_SZ]; +static short malloc_line[DBG_ARRY_BKTS][DBG_ARRY_SZ]; +static int malloc_count[DBG_ARRY_BKTS][DBG_ARRY_SZ]; +#endif +static int dbg_initd = 0; + +#define DBG_HASH_BUCKET(ptr) (((((int)ptr)>>4)+(((int)ptr)>>12)+(((int)ptr)>>20))&0xFF) + +static void +check_init(void) +{ + int B = 0, I = 0; + /* calloc the ptrs so that we don't see them when hunting lost memory */ + malloc_ptrs = calloc(DBG_ARRY_BKTS, sizeof(*malloc_ptrs)); + + for (B = 0; B < DBG_ARRY_BKTS; B++) { + for (I = 0; I < DBG_ARRY_SZ; I++) { + malloc_ptrs[B][I] = NULL; + malloc_size[B][I] = 0; +#if XMALLOC_TRACE + + malloc_file[B][I] = NULL; + malloc_line[B][I] = 0; + malloc_count[B][I] = 0; +#endif + + } + } + + dbg_initd = 1; +} + +static void +check_free(void *s) +{ + int B, I; + B = DBG_HASH_BUCKET(s); + + for (I = 0; I < DBG_ARRY_SZ; I++) { + if (malloc_ptrs[B][I] != s) + continue; + + malloc_ptrs[B][I] = NULL; + + malloc_size[B][I] = 0; + +#if XMALLOC_TRACE + + malloc_file[B][I] = NULL; + + malloc_line[B][I] = 0; + + malloc_count[B][I] = 0; + +#endif + + break; + } + + if (I == DBG_ARRY_SZ) { + static char msg[128]; + snprintf(msg, 128, "xfree: ERROR: s=%p not found!", s); + if (failure_notify) + (*failure_notify) (msg); + else + perror(msg); + } +} + +static void +check_malloc(void *p, size_t sz) +{ + void *P, *Q; + int B, I; + + if (!dbg_initd) + check_init(); + + B = DBG_HASH_BUCKET(p); + + for (I = 0; I < DBG_ARRY_SZ; I++) { + if (!(P = malloc_ptrs[B][I])) + continue; + + Q = P + malloc_size[B][I]; + + if (P <= p && p < Q) { + static char msg[128]; + snprintf(msg, 128, "xmalloc: ERROR: p=%p falls in P=%p+%d", + p, P, malloc_size[B][I]); + if (failure_notify) + (*failure_notify) (msg); + else + perror(msg); + } + } + + for (I = 0; I < DBG_ARRY_SZ; I++) { + if (malloc_ptrs[B][I]) + continue; + + malloc_ptrs[B][I] = p; + + malloc_size[B][I] = (int) sz; + +#if XMALLOC_TRACE + + malloc_file[B][I] = xmalloc_file; + + malloc_line[B][I] = xmalloc_line; + + malloc_count[B][I] = xmalloc_count; + +#endif + + break; + } + + if (I == DBG_ARRY_SZ) { + if (failure_notify) + (*failure_notify) ("xmalloc: debug out of array space!"); + else + perror("xmalloc: debug out of array space!"); + } +} + +#endif + +#if XMALLOC_TRACE && !HAVE_MALLOCBLKSIZE +size_t +xmallocblksize(void *p) +{ + int B, I; + B = DBG_HASH_BUCKET(p); + + for (I = 0; I < DBG_ARRY_SZ; I++) { + if (malloc_ptrs[B][I] == p) + return malloc_size[B][I]; + } + + return 0; +} + +#endif + +#ifdef XMALLOC_TRACE +static char * +malloc_file_name(void *p) +{ + int B, I; + B = DBG_HASH_BUCKET(p); + + for (I = 0; I < DBG_ARRY_SZ; I++) { + if (malloc_ptrs[B][I] == p) + return malloc_file[B][I]; + } + + return 0; +} + +int +malloc_line_number(void *p) +{ + int B, I; + B = DBG_HASH_BUCKET(p); + + for (I = 0; I < DBG_ARRY_SZ; I++) { + if (malloc_ptrs[B][I] == p) + return malloc_line[B][I]; + } + + return 0; +} + +int +malloc_number(void *p) +{ + int B, I; + B = DBG_HASH_BUCKET(p); + + for (I = 0; I < DBG_ARRY_SZ; I++) { + if (malloc_ptrs[B][I] == p) + return malloc_count[B][I]; + } + + return 0; +} + +static void +xmalloc_show_trace(void *p, int sign) +{ + int statMemoryAccounted(); + static size_t last_total = 0, last_accounted = 0, last_mallinfo = 0; + size_t accounted = statMemoryAccounted(); + size_t mi = 0; + size_t sz; +#if HAVE_MALLINFO + + struct mallinfo mp = mallinfo(); + mi = mp.uordblks + mp.usmblks + mp.hblkhd; +#endif + + sz = xmallocblksize(p) * sign; + xmalloc_total += sz; + xmalloc_count += sign > 0; + + if (xmalloc_trace) { + fprintf(stderr, "%c%8p size=%5d/%d acc=%5d/%d mallinfo=%5d/%d %s:%d %s", + sign > 0 ? '+' : '-', p, + (int) xmalloc_total - last_total, (int) xmalloc_total, + (int) accounted - last_accounted, (int) accounted, + (int) mi - last_mallinfo, (int) mi, + xmalloc_file, xmalloc_line, xmalloc_func); + + if (sign < 0) + fprintf(stderr, " (%d %s:%d)\n", malloc_number(p), malloc_file_name(p), malloc_line_number(p)); + else + fprintf(stderr, " %d\n", xmalloc_count); + } + + last_total = xmalloc_total; + last_accounted = accounted; + last_mallinfo = mi; +} + +short malloc_refs[DBG_ARRY_BKTS][DBG_ARRY_SZ]; +#define XMALLOC_LEAK_ALIGN (4) +static void +xmalloc_scan_region(void *start, int size, int depth) +{ + int B, I; + char *ptr = start; + char *end = ptr + size - XMALLOC_LEAK_ALIGN; + static int sum = 0; + + while (ptr <= end) { + void *p = *(void **) ptr; + + if (p && p != start) { + B = DBG_HASH_BUCKET(p); + + for (I = 0; I < DBG_ARRY_SZ; I++) { + if (malloc_ptrs[B][I] == p) { + if (!malloc_refs[B][I]++) { + /* A new reference */ + fprintf(stderr, "%*s%p %s:%d size %d allocation %d\n", + depth, "", + malloc_ptrs[B][I], malloc_file[B][I], + malloc_line[B][I], malloc_size[B][I], + malloc_count[B][I]); + sum += malloc_size[B][I]; + xmalloc_scan_region(malloc_ptrs[B][I], malloc_size[B][I], depth + 1); + + if (depth == 0) { + if (sum != malloc_size[B][I]) + fprintf(stderr, "=== %d bytes\n", sum); + + sum = 0; + } + +#if XMALLOC_SHOW_ALL_REFERENCES + + } else { + /* We have already scanned this pointer... */ + fprintf(stderr, "%*s%p %s:%d size %d allocation %d ... (%d)\n", + depth * 2, "", + malloc_ptrs[B][I], malloc_file[B][I], + malloc_line[B][I], malloc_size[B][I], + malloc_count[B][I], malloc_refs[B][I]); +#endif + + } + } + } + } + + ptr += XMALLOC_LEAK_ALIGN; + } +} + +void +xmalloc_find_leaks(void) +{ + int B, I; + int leak_sum = 0; + + extern void _etext; + fprintf(stderr, "----- Memory map ----\n"); + xmalloc_scan_region(&_etext, (void *) sbrk(0) - (void *) &_etext, 0); + + for (B = 0; B < DBG_ARRY_BKTS; B++) { + for (I = 0; I < DBG_ARRY_SZ; I++) { + if (malloc_ptrs[B][I] && malloc_refs[B][I] == 0) { + /* Found a leak... */ + fprintf(stderr, "Leak found: %p", malloc_ptrs[B][I]); + fprintf(stderr, " %s", malloc_file[B][I]); + fprintf(stderr, ":%d", malloc_line[B][I]); + fprintf(stderr, " size %d", malloc_size[B][I]); + fprintf(stderr, " allocation %d\n", malloc_count[B][I]); + leak_sum += malloc_size[B][I]; + } + } + } + + if (leak_sum) { + fprintf(stderr, "Total leaked memory: %d\n", leak_sum); + } else { + fprintf(stderr, "No memory leaks detected\n"); + } + + fprintf(stderr, "----------------------\n"); +} + +#endif /* XMALLOC_TRACE */ diff --git a/lib/util.c b/lib/util.c index cc5979e411..b1fd1ccdc6 100644 --- a/lib/util.c +++ b/lib/util.c @@ -50,374 +50,9 @@ #if HAVE_UNISTD_H #include #endif -#if HAVE_GNUMALLLOC_H -#include -#elif HAVE_MALLOC_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif #if HAVE_MATH_H #include #endif -#if HAVE_ASSERT_H -#include -#endif - -static void default_failure_notify(const char *); - -void (*failure_notify) (const char *) = default_failure_notify; - -#if MEM_GEN_TRACE - -static FILE *tracefp = NULL; - -void -log_trace_init(char *fn) -{ - tracefp = fopen(fn, "a+"); - - if (!tracefp) { - perror("log_trace_init"); - exit(1); - } -} - -void -log_trace_done() -{ - fclose(tracefp); - tracefp = NULL; -} - -#endif - -#if XMALLOC_TRACE -char *xmalloc_file = ""; -int xmalloc_line = 0; -char *xmalloc_func = ""; -static int xmalloc_count = 0; -int xmalloc_trace = 0; /* Enable with -m option */ -size_t xmalloc_total = 0; -#undef xmalloc -#undef xfree -#undef xxfree -#undef xrealloc -#undef xcalloc -#undef xstrdup -#endif - -#if XMALLOC_DEBUG -#define DBG_ARRY_SZ (1<<11) -#define DBG_ARRY_BKTS (1<<8) -static void *(*malloc_ptrs)[DBG_ARRY_SZ]; -static int malloc_size[DBG_ARRY_BKTS][DBG_ARRY_SZ]; -#if XMALLOC_TRACE -static char *malloc_file[DBG_ARRY_BKTS][DBG_ARRY_SZ]; -static short malloc_line[DBG_ARRY_BKTS][DBG_ARRY_SZ]; -static int malloc_count[DBG_ARRY_BKTS][DBG_ARRY_SZ]; -#endif -static int dbg_initd = 0; - -#define DBG_HASH_BUCKET(ptr) (((((int)ptr)>>4)+(((int)ptr)>>12)+(((int)ptr)>>20))&0xFF) - -static void -check_init(void) -{ - int B = 0, I = 0; - /* calloc the ptrs so that we don't see them when hunting lost memory */ - malloc_ptrs = calloc(DBG_ARRY_BKTS, sizeof(*malloc_ptrs)); - - for (B = 0; B < DBG_ARRY_BKTS; B++) { - for (I = 0; I < DBG_ARRY_SZ; I++) { - malloc_ptrs[B][I] = NULL; - malloc_size[B][I] = 0; -#if XMALLOC_TRACE - - malloc_file[B][I] = NULL; - malloc_line[B][I] = 0; - malloc_count[B][I] = 0; -#endif - - } - } - - dbg_initd = 1; -} - -static void -check_free(void *s) -{ - int B, I; - B = DBG_HASH_BUCKET(s); - - for (I = 0; I < DBG_ARRY_SZ; I++) { - if (malloc_ptrs[B][I] != s) - continue; - - malloc_ptrs[B][I] = NULL; - - malloc_size[B][I] = 0; - -#if XMALLOC_TRACE - - malloc_file[B][I] = NULL; - - malloc_line[B][I] = 0; - - malloc_count[B][I] = 0; - -#endif - - break; - } - - if (I == DBG_ARRY_SZ) { - static char msg[128]; - snprintf(msg, 128, "xfree: ERROR: s=%p not found!", s); - (*failure_notify) (msg); - } -} - -static void -check_malloc(void *p, size_t sz) -{ - void *P, *Q; - int B, I; - - if (!dbg_initd) - check_init(); - - B = DBG_HASH_BUCKET(p); - - for (I = 0; I < DBG_ARRY_SZ; I++) { - if (!(P = malloc_ptrs[B][I])) - continue; - - Q = P + malloc_size[B][I]; - - if (P <= p && p < Q) { - static char msg[128]; - snprintf(msg, 128, "xmalloc: ERROR: p=%p falls in P=%p+%d", - p, P, malloc_size[B][I]); - (*failure_notify) (msg); - } - } - - for (I = 0; I < DBG_ARRY_SZ; I++) { - if (malloc_ptrs[B][I]) - continue; - - malloc_ptrs[B][I] = p; - - malloc_size[B][I] = (int) sz; - -#if XMALLOC_TRACE - - malloc_file[B][I] = xmalloc_file; - - malloc_line[B][I] = xmalloc_line; - - malloc_count[B][I] = xmalloc_count; - -#endif - - break; - } - - if (I == DBG_ARRY_SZ) - (*failure_notify) ("xmalloc: debug out of array space!"); -} - -#endif - -#if XMALLOC_TRACE && !HAVE_MALLOCBLKSIZE -size_t -xmallocblksize(void *p) -{ - int B, I; - B = DBG_HASH_BUCKET(p); - - for (I = 0; I < DBG_ARRY_SZ; I++) { - if (malloc_ptrs[B][I] == p) - return malloc_size[B][I]; - } - - return 0; -} - -#endif - -#ifdef XMALLOC_TRACE -static char * -malloc_file_name(void *p) -{ - int B, I; - B = DBG_HASH_BUCKET(p); - - for (I = 0; I < DBG_ARRY_SZ; I++) { - if (malloc_ptrs[B][I] == p) - return malloc_file[B][I]; - } - - return 0; -} - -int -malloc_line_number(void *p) -{ - int B, I; - B = DBG_HASH_BUCKET(p); - - for (I = 0; I < DBG_ARRY_SZ; I++) { - if (malloc_ptrs[B][I] == p) - return malloc_line[B][I]; - } - - return 0; -} - -int -malloc_number(void *p) -{ - int B, I; - B = DBG_HASH_BUCKET(p); - - for (I = 0; I < DBG_ARRY_SZ; I++) { - if (malloc_ptrs[B][I] == p) - return malloc_count[B][I]; - } - - return 0; -} - -static void -xmalloc_show_trace(void *p, int sign) -{ - int statMemoryAccounted(); - static size_t last_total = 0, last_accounted = 0, last_mallinfo = 0; - size_t accounted = statMemoryAccounted(); - size_t mi = 0; - size_t sz; -#if HAVE_MALLINFO - - struct mallinfo mp = mallinfo(); - mi = mp.uordblks + mp.usmblks + mp.hblkhd; -#endif - - sz = xmallocblksize(p) * sign; - xmalloc_total += sz; - xmalloc_count += sign > 0; - - if (xmalloc_trace) { - fprintf(stderr, "%c%8p size=%5d/%d acc=%5d/%d mallinfo=%5d/%d %s:%d %s", - sign > 0 ? '+' : '-', p, - (int) xmalloc_total - last_total, (int) xmalloc_total, - (int) accounted - last_accounted, (int) accounted, - (int) mi - last_mallinfo, (int) mi, - xmalloc_file, xmalloc_line, xmalloc_func); - - if (sign < 0) - fprintf(stderr, " (%d %s:%d)\n", malloc_number(p), malloc_file_name(p), malloc_line_number(p)); - else - fprintf(stderr, " %d\n", xmalloc_count); - } - - last_total = xmalloc_total; - last_accounted = accounted; - last_mallinfo = mi; -} - -short malloc_refs[DBG_ARRY_BKTS][DBG_ARRY_SZ]; -#define XMALLOC_LEAK_ALIGN (4) -static void -xmalloc_scan_region(void *start, int size, int depth) -{ - int B, I; - char *ptr = start; - char *end = ptr + size - XMALLOC_LEAK_ALIGN; - static int sum = 0; - - while (ptr <= end) { - void *p = *(void **) ptr; - - if (p && p != start) { - B = DBG_HASH_BUCKET(p); - - for (I = 0; I < DBG_ARRY_SZ; I++) { - if (malloc_ptrs[B][I] == p) { - if (!malloc_refs[B][I]++) { - /* A new reference */ - fprintf(stderr, "%*s%p %s:%d size %d allocation %d\n", - depth, "", - malloc_ptrs[B][I], malloc_file[B][I], - malloc_line[B][I], malloc_size[B][I], - malloc_count[B][I]); - sum += malloc_size[B][I]; - xmalloc_scan_region(malloc_ptrs[B][I], malloc_size[B][I], depth + 1); - - if (depth == 0) { - if (sum != malloc_size[B][I]) - fprintf(stderr, "=== %d bytes\n", sum); - - sum = 0; - } - -#if XMALLOC_SHOW_ALL_REFERENCES - - } else { - /* We have already scanned this pointer... */ - fprintf(stderr, "%*s%p %s:%d size %d allocation %d ... (%d)\n", - depth * 2, "", - malloc_ptrs[B][I], malloc_file[B][I], - malloc_line[B][I], malloc_size[B][I], - malloc_count[B][I], malloc_refs[B][I]); -#endif - - } - } - } - } - - ptr += XMALLOC_LEAK_ALIGN; - } -} - -void -xmalloc_find_leaks(void) -{ - int B, I; - int leak_sum = 0; - - extern void _etext; - fprintf(stderr, "----- Memory map ----\n"); - xmalloc_scan_region(&_etext, (void *) sbrk(0) - (void *) &_etext, 0); - - for (B = 0; B < DBG_ARRY_BKTS; B++) { - for (I = 0; I < DBG_ARRY_SZ; I++) { - if (malloc_ptrs[B][I] && malloc_refs[B][I] == 0) { - /* Found a leak... */ - fprintf(stderr, "Leak found: %p", malloc_ptrs[B][I]); - fprintf(stderr, " %s", malloc_file[B][I]); - fprintf(stderr, ":%d", malloc_line[B][I]); - fprintf(stderr, " size %d", malloc_size[B][I]); - fprintf(stderr, " allocation %d\n", malloc_count[B][I]); - leak_sum += malloc_size[B][I]; - } - } - } - - if (leak_sum) { - fprintf(stderr, "Total leaked memory: %d\n", leak_sum); - } else { - fprintf(stderr, "No memory leaks detected\n"); - } - - fprintf(stderr, "----------------------\n"); -} - -#endif /* XMALLOC_TRACE */ void Tolower(char *q) @@ -505,15 +140,6 @@ xint64toa(int64_t num) return buf; } -/* A default failure notifier when the main program hasn't installed any */ -void -default_failure_notify(const char *message) -{ - if (write(2, message, strlen(message))) {} - if (write(2, "\n", 1)) {} - abort(); -} - void gb_flush(gb_t * g) { diff --git a/src/main.cc b/src/main.cc index 7421245237..7871413714 100644 --- a/src/main.cc +++ b/src/main.cc @@ -132,9 +132,6 @@ void WINAPI WIN32_svcHandler(DWORD); #define SQUID_BUILD_INFO "" #endif -/** for error reporting from xmalloc and friends */ -SQUIDCEXTERN void (*failure_notify) (const char *); - static char *opt_syslog_facility = NULL; static int icpPortNumOverride = 1; /* Want to detect "-u 0" */ static int configured_once = 0; diff --git a/src/tools.cc b/src/tools.cc index 2ccfb99a13..f3118949e9 100644 --- a/src/tools.cc +++ b/src/tools.cc @@ -86,8 +86,6 @@ SQUIDCEXTERN int setresuid(uid_t, uid_t, uid_t); #endif /* _SQUID_LINUX */ -SQUIDCEXTERN void (*failure_notify) (const char *); - void releaseServerSockets(void) {