[asterisk-commits] mmichelson: trunk r118173 - in /trunk: ./ include/asterisk/ main/ utils/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri May 23 17:35:51 CDT 2008


Author: mmichelson
Date: Fri May 23 17:35:50 2008
New Revision: 118173

URL: http://svn.digium.com/view/asterisk?view=rev&rev=118173
Log:
A new feature thanks to the fine folks at Switchvox!

If a deadlock is detected, then the typical lock information will be
printed along with a backtrace of the stack for the offending threads.
Use of this requires compiling with DETECT_DEADLOCKS and having glibc
installed.

Furthermore, issuing the "core show locks" CLI command will print the
normal lock information as well as a backtraces for each lock. This
requires that DEBUG_THREADS is enabled and that glibc is installed.

All the backtrace features may be disabled by running the configure
script with --without-execinfo as an argument


Modified:
    trunk/CHANGES
    trunk/include/asterisk/lock.h
    trunk/include/asterisk/logger.h
    trunk/main/logger.c
    trunk/main/utils.c
    trunk/utils/ael_main.c
    trunk/utils/check_expr.c
    trunk/utils/conf2ael.c
    trunk/utils/hashtest.c
    trunk/utils/hashtest2.c
    trunk/utils/refcounter.c

Modified: trunk/CHANGES
URL: http://svn.digium.com/view/asterisk/trunk/CHANGES?view=diff&rev=118173&r1=118172&r2=118173
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Fri May 23 17:35:50 2008
@@ -744,3 +744,9 @@
      turned on, via the CHANNEL(trace) dialplan function.  Could be useful for
      dialplan debugging.
   * iLBC source code no longer included (see UPGRADE.txt for details)
+  * If compiled with DETECT_DEADLOCKS enabled and if you have glibc, then if 
+     deadlock is detected, a backtrace of the stack which led to the lock calls
+	 will be output to the CLI.
+  * If compiled with DEBUG_THREADS enabled and if you have glibc, then issuing
+     the "core show locks" CLI command will give lock information output as well
+	 as a backtrace of the stack which led to the lock calls.

Modified: trunk/include/asterisk/lock.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/lock.h?view=diff&rev=118173&r1=118172&r2=118173
==============================================================================
--- trunk/include/asterisk/lock.h (original)
+++ trunk/include/asterisk/lock.h Fri May 23 17:35:50 2008
@@ -51,6 +51,8 @@
 #include <pthread.h>
 #include <sys/param.h>
 
+#include <execinfo.h>
+
 #include "asterisk/logger.h"
 
 /* internal macro to profile mutexes. Only computes the delay on
@@ -108,9 +110,15 @@
 
 #include <errno.h>
 
+#ifdef HAVE_BKTR
+#define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }
+#define AST_MUTEX_INIT_VALUE_NOTRACKING \
+                             { PTHREAD_MUTEX_INIT_VALUE, 0, { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }
+#else
 #define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
 #define AST_MUTEX_INIT_VALUE_NOTRACKING \
                              { PTHREAD_MUTEX_INIT_VALUE, 0, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
+#endif
 
 #define AST_MAX_REENTRANCY 10
 
@@ -125,6 +133,9 @@
 	int reentrancy;
 	const char *func[AST_MAX_REENTRANCY];
 	pthread_t thread[AST_MAX_REENTRANCY];
+#ifdef HAVE_BKTR
+	struct ast_bt backtrace[AST_MAX_REENTRANCY];
+#endif
 	pthread_mutex_t reentr_mutex;
 };
 
@@ -149,12 +160,22 @@
  * on the lock.  ast_mark_lock_acquired() will mark it as held by this thread.
  */
 #if !defined(LOW_MEMORY)
+#ifdef HAVE_BKTR
+void ast_store_lock_info(enum ast_lock_type type, const char *filename,
+	int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt);
+#else
 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
 	int line_num, const char *func, const char *lock_name, void *lock_addr);
+#endif /* HAVE_BKTR */
+
+#else
+
+#ifdef HAVE_BKTR
+#define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS,BUD)
 #else
 #define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS)
-#endif
-
+#endif /* HAVE_BKTR */
+#endif /* !defined(LOW_MEMORY) */
 
 /*!
  * \brief Mark the last lock as acquired
@@ -181,12 +202,34 @@
  * be removed from the current thread's lock info struct.
  */
 #if !defined(LOW_MEMORY)
+#ifdef HAVE_BKTR
+void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt);
+#else
 void ast_remove_lock_info(void *lock_addr);
+#endif /* HAVE_BKTR */
+#else
+#ifdef HAVE_BKTR
+#define ast_remove_lock_info(ignore,me)
 #else
 #define ast_remove_lock_info(ignore)
-#endif
-
-
+#endif /* HAVE_BKTR */
+#endif /* !defined(LOW_MEMORY) */
+
+#ifdef HAVE_BKTR
+static inline void __dump_backtrace(struct ast_bt *bt, int canlog)
+{
+	char **strings;
+
+	size_t i;
+
+	strings = backtrace_symbols(bt->addresses, bt->num_frames);
+
+	for (i = 0; i < bt->num_frames; i++)
+		__ast_mutex_logger("%s\n", strings[i]);
+
+	free(strings);
+}
+#endif
 
 /*!
  * \brief log info for the current lock with ast_log().
@@ -223,6 +266,9 @@
 		p_ast_mutex->lineno[i] = 0;
 		p_ast_mutex->func[i] = NULL;
 		p_ast_mutex->thread[i] = 0;
+#ifdef HAVE_BKTR
+		memset(&p_ast_mutex->backtrace[i], 0, sizeof(p_ast_mutex->backtrace[i]));
+#endif
 	}
 
 	p_ast_mutex->reentrancy = 0;
@@ -308,6 +354,9 @@
 		ast_reentrancy_lock(t);
 		__ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
 			    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+		__dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
+#endif
 		ast_reentrancy_unlock(t);
 		break;
 	}
@@ -325,6 +374,9 @@
 	t->func[0] = func;
 	t->reentrancy = 0;
 	t->thread[0] = 0;
+#ifdef HAVE_BKTR
+	memset(&t->backtrace[0], 0, sizeof(t->backtrace[0]));
+#endif
 	ast_reentrancy_unlock(t);
 	delete_reentrancy_cs(t);
 
@@ -336,6 +388,9 @@
 {
 	int res;
 	int canlog = strcmp(filename, "logger.c") & t->track;
+#ifdef HAVE_BKTR
+	struct ast_bt *bt = NULL;
+#endif
 
 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
 	if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
@@ -352,8 +407,17 @@
 	}
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
 
-	if (t->track)
+	if (t->track) {
+#ifdef HAVE_BKTR
+		ast_reentrancy_lock(t);
+		ast_bt_get_addresses(&t->backtrace[t->reentrancy]);
+		bt = &t->backtrace[t->reentrancy];
+		ast_reentrancy_unlock(t);
+		ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
+#else
 		ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
+#endif
+	}
 
 #ifdef DETECT_DEADLOCKS
 	{
@@ -373,9 +437,15 @@
 					__ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
 							   filename, lineno, func, (int) wait_time, mutex_name);
 					ast_reentrancy_lock(t);
+#ifdef HAVE_BKTR
+					__dump_backtrace(&t->backtrace[t->reentrancy], canlog);
+#endif
 					__ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
 							   t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
 							   t->func[t->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+					__dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
+#endif
 					ast_reentrancy_unlock(t);
 					reported_wait = wait_time;
 				}
@@ -409,8 +479,20 @@
 		if (t->track)
 			ast_mark_lock_acquired(&t->mutex);
 	} else {
+#ifdef HAVE_BKTR
+		if (t->reentrancy) {
+			ast_reentrancy_lock(t);
+			bt = &t->backtrace[t->reentrancy-1];
+			ast_reentrancy_unlock(t);
+		} else {
+			bt = NULL;
+		}
+		if (t->track)
+			ast_remove_lock_info(&t->mutex, bt);
+#else
 		if (t->track)
 			ast_remove_lock_info(&t->mutex);
+#endif
 		__ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
 				   filename, lineno, func, strerror(res));
 		DO_THREAD_CRASH;
@@ -424,6 +506,9 @@
 {
 	int res;
 	int canlog = strcmp(filename, "logger.c") & t->track;
+#ifdef HAVE_BKTR
+	struct ast_bt *bt = NULL;
+#endif
 
 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
 	if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
@@ -440,8 +525,17 @@
 	}
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
 
-	if (t->track)
+	if (t->track) {
+#ifdef HAVE_BKTR
+		ast_reentrancy_lock(t);
+		ast_bt_get_addresses(&t->backtrace[t->reentrancy]);
+		bt = &t->backtrace[t->reentrancy];
+		ast_reentrancy_unlock(t);
+		ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
+#else
 		ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
+#endif
+	}
 
 	if (!(res = pthread_mutex_trylock(&t->mutex))) {
 		ast_reentrancy_lock(t);
@@ -470,6 +564,9 @@
 {
 	int res;
 	int canlog = strcmp(filename, "logger.c") & t->track;
+#ifdef HAVE_BKTR
+	struct ast_bt *bt = NULL;
+#endif
 
 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
 	if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
@@ -490,6 +587,9 @@
 				   filename, lineno, func, mutex_name);
 		__ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
 				   t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+		__dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
+#endif
 		DO_THREAD_CRASH;
 	}
 
@@ -505,11 +605,21 @@
 		t->func[t->reentrancy] = NULL;
 		t->thread[t->reentrancy] = 0;
 	}
+
+#ifdef HAVE_BKTR
+	if (t->reentrancy) {
+		bt = &t->backtrace[t->reentrancy - 1];
+	}
+#endif
 	ast_reentrancy_unlock(t);
 
-	if (t->track)
+	if (t->track) {
+#ifdef HAVE_BKTR
+		ast_remove_lock_info(&t->mutex, bt);
+#else
 		ast_remove_lock_info(&t->mutex);
-
+#endif
+	}
 	if ((res = pthread_mutex_unlock(&t->mutex))) {
 		__ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n", 
 				   filename, lineno, func, strerror(res));
@@ -549,6 +659,9 @@
 {
 	int res;
 	int canlog = strcmp(filename, "logger.c") & t->track;
+#ifdef HAVE_BKTR
+	struct ast_bt *bt = NULL;
+#endif
 
 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
 	if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
@@ -569,6 +682,9 @@
 				   filename, lineno, func, mutex_name);
 		__ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
 				   t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+		__dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
+#endif
 		DO_THREAD_CRASH;
 	}
 
@@ -584,10 +700,21 @@
 		t->func[t->reentrancy] = NULL;
 		t->thread[t->reentrancy] = 0;
 	}
+
+#ifdef HAVE_BKTR
+	if (t->reentrancy) {
+		bt = &t->backtrace[t->reentrancy - 1];
+	}
+#endif
 	ast_reentrancy_unlock(t);
 
-	if (t->track)
+	if (t->track) {
+#ifdef HAVE_BKTR
+		ast_remove_lock_info(&t->mutex, bt);
+#else
 		ast_remove_lock_info(&t->mutex);
+#endif
+	}
 
 	if ((res = pthread_cond_wait(cond, &t->mutex))) {
 		__ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
@@ -600,6 +727,10 @@
 			t->lineno[t->reentrancy] = lineno;
 			t->func[t->reentrancy] = func;
 			t->thread[t->reentrancy] = pthread_self();
+#ifdef HAVE_BKTR
+			ast_bt_get_addresses(&t->backtrace[t->reentrancy]);
+			bt = &t->backtrace[t->reentrancy];
+#endif
 			t->reentrancy++;
 		} else {
 			__ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
@@ -607,8 +738,13 @@
 		}
 		ast_reentrancy_unlock(t);
 
-		if (t->track)
+		if (t->track) {
+#ifdef HAVE_BKTR
+			ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
+#else
 			ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
+#endif
+		}
 	}
 
 	return res;
@@ -620,6 +756,9 @@
 {
 	int res;
 	int canlog = strcmp(filename, "logger.c") & t->track;
+#ifdef HAVE_BKTR
+	struct ast_bt *bt = NULL;
+#endif
 
 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
 	if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
@@ -640,6 +779,9 @@
 				   filename, lineno, func, mutex_name);
 		__ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
 				   t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
+#ifdef HAVE_BKTR
+		__dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
+#endif
 		DO_THREAD_CRASH;
 	}
 
@@ -655,10 +797,19 @@
 		t->func[t->reentrancy] = NULL;
 		t->thread[t->reentrancy] = 0;
 	}
+#ifdef HAVE_BKTR
+	if (t->reentrancy) {
+		bt = &t->backtrace[t->reentrancy - 1];
+	}
+#endif
 	ast_reentrancy_unlock(t);
 
 	if (t->track)
+#ifdef HAVE_BKTR
+		ast_remove_lock_info(&t->mutex, bt);
+#else
 		ast_remove_lock_info(&t->mutex);
+#endif
 
 	if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
 		__ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
@@ -671,6 +822,10 @@
 			t->lineno[t->reentrancy] = lineno;
 			t->func[t->reentrancy] = func;
 			t->thread[t->reentrancy] = pthread_self();
+#ifdef HAVE_BKTR
+			ast_bt_get_addresses(&t->backtrace[t->reentrancy]);
+			bt = &t->backtrace[t->reentrancy];
+#endif
 			t->reentrancy++;
 		} else {
 			__ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
@@ -678,8 +833,13 @@
 		}
 		ast_reentrancy_unlock(t);
 
-		if (t->track)
+		if (t->track) {
+#ifdef HAVE_BKTR
+			ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
+#else
 			ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
+#endif
+		}
 	}
 
 	return res;
@@ -696,8 +856,265 @@
 #define ast_cond_wait(cond, mutex)		__ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
 #define ast_cond_timedwait(cond, mutex, time)	__ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
 
+struct ast_rwlock_info {
+	pthread_rwlock_t lock;
+#ifdef HAVE_BKTR
+	struct ast_bt backtrace;
+#endif
+};
+
+typedef struct ast_rwlock_info ast_rwlock_t;
+
+#define ast_rwlock_init(rwlock)		__ast_rwlock_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
+#define ast_rwlock_destroy(rwlock)	__ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
+#define ast_rwlock_unlock(a)		_ast_rwlock_unlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ast_rwlock_rdlock(a)		_ast_rwlock_rdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ast_rwlock_wrlock(a)		_ast_rwlock_wrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ast_rwlock_tryrdlock(a)		_ast_rwlock_tryrdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ast_rwlock_trywrlock(a) _ast_rwlock_trywrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+#ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
+#ifdef HAVE_BKTR
+#define AST_RWLOCK_INIT_VALUE { PTHREAD_RWLOCK_INITIALIZER, {{0,},} }
+#else
+#define AST_RWLOCK_INIT_VALUE { PTHREAD_RWLOCK_INITIALIZER }
+#endif /* HAVE_BKTR */
+#else  /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
+#ifdef HAVE_BKTR
+#define AST_RWLOCK_INIT_VALUE { 0 , {0,},}}
+#else
+#define AST_RWLOCK_INIT_VALUE { 0 }
+#endif /* HAVE_BKTR */
+#endif /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
+
+static inline int __ast_rwlock_init(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *prwlock)
+{
+	int res;
+	pthread_rwlockattr_t attr;
+#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
+        int canlog = strcmp(filename, "logger.c");
+
+        if (*prwlock != ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+		__ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
+				filename, lineno, func, rwlock_name);
+		return 0;
+	}
+#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
+	pthread_rwlockattr_init(&attr);
+
+#ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
+	pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
+#endif
+
+	res = pthread_rwlock_init(&prwlock->lock, &attr);
+	pthread_rwlockattr_destroy(&attr);
+	return res;
+}
+
+
+static inline int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *prwlock)
+{
+	int res;
+	int canlog = strcmp(filename, "logger.c");
+
+#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
+	if (*prwlock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+		__ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
+				   filename, lineno, func, rwlock_name);
+		return 0;
+	}
+#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
+	
+	if ((res = pthread_rwlock_destroy(&prwlock->lock)))
+		__ast_mutex_logger("%s line %d (%s): Error destroying rwlock %s: %s\n",
+				filename, lineno, func, rwlock_name, strerror(res));
+
+	return res;
+}
+
+
+static inline int _ast_rwlock_unlock(ast_rwlock_t *lock, const char *name,
+	const char *file, int line, const char *func)
+{
+	int res;
+#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
+	int canlog = strcmp(file, "logger.c");
+
+	if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+		__ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
+				   file, line, func, name);
+		res = __ast_rwlock_init(file, line, func, name, lock);
+		if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+			__ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
+					file, line, func, name);
+		}
+		return res;
+	}
+#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
+	
+	res = pthread_rwlock_unlock(&lock->lock);
+#ifdef HAVE_BKTR
+	memset(&lock->backtrace, 0, sizeof(lock->backtrace));
+	ast_remove_lock_info(lock, NULL);
+#else
+	ast_remove_lock_info(lock);
+#endif
+	return res;
+}
+
+
+static inline int _ast_rwlock_rdlock(ast_rwlock_t *lock, const char *name,
+	const char *file, int line, const char *func)
+{
+	int res;
+#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
+	int canlog = strcmp(file, "logger.c");
+	
+	if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+		 /* Don't warn abount uninitialized lock.
+		  * Simple try to initialize it.
+		  * May be not needed in linux system.
+		  */
+		res = __ast_rwlock_init(file, line, func, name, lock);
+		if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+			__ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
+					file, line, func, name);
+			return res;
+		}
+	}
+#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
+#ifdef HAVE_BKTR	
+	ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock, &lock->backtrace);
+#else
+	ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock);
+#endif
+	res = pthread_rwlock_rdlock(&lock->lock);
+	if (!res)
+		ast_mark_lock_acquired(lock);
+	else
+#ifdef HAVE_BKTR
+		ast_remove_lock_info(lock, NULL);
+#else
+		ast_remove_lock_info(lock);
+#endif
+	return res;
+}
+
+
+static inline int _ast_rwlock_wrlock(ast_rwlock_t *lock, const char *name,
+	const char *file, int line, const char *func)
+{
+	int res;
+#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
+	int canlog = strcmp(file, "logger.c");
+	
+	if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+		 /* Don't warn abount uninitialized lock.
+		  * Simple try to initialize it.
+		  * May be not needed in linux system.
+		  */
+		res = __ast_rwlock_init(file, line, func, name, lock);
+		if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+			__ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
+					file, line, func, name);
+			return res;
+		}
+	}
+#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
+#ifdef HAVE_BKTR
+	ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock, &lock->backtrace);
+#else
+	ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock);
+#endif
+	res = pthread_rwlock_wrlock(&lock->lock);
+	if (!res)
+		ast_mark_lock_acquired(lock);
+	else
+#ifdef HAVE_BKTR
+		ast_remove_lock_info(lock, NULL);
+#else
+		ast_remove_lock_info(lock);
+#endif
+	return res;
+}
+
+
+static inline int _ast_rwlock_tryrdlock(ast_rwlock_t *lock, const char *name,
+	const char *file, int line, const char *func)
+{
+	int res;
+#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
+	int canlog = strcmp(file, "logger.c");
+	
+	if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+		 /* Don't warn abount uninitialized lock.
+		  * Simple try to initialize it.
+		  * May be not needed in linux system.
+		  */
+		res = __ast_rwlock_init(file, line, func, name, lock);
+		if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+			__ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
+					file, line, func, name);
+			return res;
+		}
+	}
+#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
+#ifdef HAVE_BKTR
+	ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock, &lock->backtrace);
+#else
+	ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock);
+#endif
+	res = pthread_rwlock_tryrdlock(&lock->lock);
+	if (!res)
+		ast_mark_lock_acquired(lock);
+	else
+#ifdef HAVE_BKTR
+		ast_remove_lock_info(lock, NULL);
+#else
+		ast_remove_lock_info(lock);
+#endif
+	return res;
+}
+
+
+static inline int _ast_rwlock_trywrlock(ast_rwlock_t *lock, const char *name,
+	const char *file, int line, const char *func)
+{
+	int res;
+#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
+	int canlog = strcmp(file, "logger.c");
+	
+	if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+		 /* Don't warn abount uninitialized lock.
+		  * Simple try to initialize it.
+		  * May be not needed in linux system.
+		  */
+		res = __ast_rwlock_init(file, line, func, name, lock);
+		if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
+			__ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
+					file, line, func, name);
+			return res;
+		}
+	}
+#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
+#ifdef HAVE_BKTR
+	ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock, &lock->backtrace);
+#else
+	ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock);
+#endif
+	res = pthread_rwlock_trywrlock(&lock->lock);
+	if (!res)
+		ast_mark_lock_acquired(lock);
+	else
+#ifdef HAVE_BKTR
+		ast_remove_lock_info(lock, NULL);
+#else
+		ast_remove_lock_info(lock);
+#endif
+	return res;
+}
+
 #else /* !DEBUG_THREADS */
-
 
 typedef pthread_mutex_t ast_mutex_t;
 
@@ -771,6 +1188,61 @@
 static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
 {
 	return pthread_cond_timedwait(cond, t, abstime);
+}
+
+
+typedef pthread_rwlock_t ast_rwlock_t;
+
+#ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
+#define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
+#else
+#define AST_RWLOCK_INIT_VALUE { 0 }
+#endif
+
+static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
+{
+	int res;
+	pthread_rwlockattr_t attr;
+
+	pthread_rwlockattr_init(&attr);
+
+#ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
+	pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
+#endif
+
+	res = pthread_rwlock_init(prwlock, &attr);
+	pthread_rwlockattr_destroy(&attr);
+	return res;
+}
+
+static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
+{
+	return pthread_rwlock_destroy(prwlock);
+}
+
+static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
+{
+	return pthread_rwlock_unlock(prwlock);
+}
+
+static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
+{
+	return pthread_rwlock_rdlock(prwlock);
+}
+
+static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
+{
+	return pthread_rwlock_tryrdlock(prwlock);
+}
+
+static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
+{
+	return pthread_rwlock_wrlock(prwlock);
+}
+
+static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
+{
+	return pthread_rwlock_trywrlock(prwlock);
 }
 
 #endif /* !DEBUG_THREADS */
@@ -826,274 +1298,6 @@
 #define pthread_create __use_ast_pthread_create_instead__
 #endif
 
-/*
- * Same as above, definitions of ast_rwlock_t for the various cases:
- * simple wrappers for the pthread equivalent in the non-debug case,
- * more sophisticated tracking in the debug case.
- */
-
-typedef pthread_rwlock_t ast_rwlock_t;
-
-#ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
-#define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
-#else
-#define AST_RWLOCK_INIT_VALUE { 0 }
-#endif
-
-#ifdef DEBUG_THREADS
-
-#define ast_rwlock_init(rwlock)		__ast_rwlock_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
-#define ast_rwlock_destroy(rwlock)	__ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
-#define ast_rwlock_unlock(a)		_ast_rwlock_unlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ast_rwlock_rdlock(a)		_ast_rwlock_rdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ast_rwlock_wrlock(a)		_ast_rwlock_wrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ast_rwlock_tryrdlock(a)		_ast_rwlock_tryrdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ast_rwlock_trywrlock(a) _ast_rwlock_trywrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-
-static inline int __ast_rwlock_init(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *prwlock)
-{
-	int res;
-	pthread_rwlockattr_t attr;
-#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
-        int canlog = strcmp(filename, "logger.c");
-
-        if (*prwlock != ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
-		__ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
-				filename, lineno, func, rwlock_name);
-		return 0;
-	}
-#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-	pthread_rwlockattr_init(&attr);
-
-#ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
-	pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
-#endif
-
-	res = pthread_rwlock_init(prwlock, &attr);
-	pthread_rwlockattr_destroy(&attr);
-	return res;
-}
-
-
-static inline int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *prwlock)
-{
-	int res;
-	int canlog = strcmp(filename, "logger.c");
-
-#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
-	if (*prwlock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
-		__ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
-				   filename, lineno, func, rwlock_name);
-		return 0;
-	}
-#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-	
-	if ((res = pthread_rwlock_destroy(prwlock)))
-		__ast_mutex_logger("%s line %d (%s): Error destroying rwlock %s: %s\n",
-				filename, lineno, func, rwlock_name, strerror(res));
-
-	return res;
-}
-
-
-static inline int _ast_rwlock_unlock(ast_rwlock_t *lock, const char *name,
-	const char *file, int line, const char *func)
-{
-	int res;
-#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
-	int canlog = strcmp(file, "logger.c");
-
-	if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
-		__ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
-				   file, line, func, name);
-		res = __ast_rwlock_init(file, line, func, name, lock);
-		if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
-			__ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
-					file, line, func, name);
-		}
-		return res;
-	}
-#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-	
-	res = pthread_rwlock_unlock(lock);
-	ast_remove_lock_info(lock);
-	return res;
-}
-
-
-static inline int _ast_rwlock_rdlock(ast_rwlock_t *lock, const char *name,
-	const char *file, int line, const char *func)
-{
-	int res;
-#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
-	int canlog = strcmp(file, "logger.c");
-	
-	if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
-		 /* Don't warn abount uninitialized lock.
-		  * Simple try to initialize it.
-		  * May be not needed in linux system.
-		  */
-		res = __ast_rwlock_init(file, line, func, name, lock);
-		if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
-			__ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
-					file, line, func, name);
-			return res;
-		}
-	}
-#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-	
-	ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock);
-	res = pthread_rwlock_rdlock(lock);
-	if (!res)
-		ast_mark_lock_acquired(lock);
-	else
-		ast_remove_lock_info(lock);
-	return res;
-}
-
-
-static inline int _ast_rwlock_wrlock(ast_rwlock_t *lock, const char *name,
-	const char *file, int line, const char *func)
-{
-	int res;
-#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
-	int canlog = strcmp(file, "logger.c");
-	
-	if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
-		 /* Don't warn abount uninitialized lock.
-		  * Simple try to initialize it.
-		  * May be not needed in linux system.
-		  */
-		res = __ast_rwlock_init(file, line, func, name, lock);
-		if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
-			__ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
-					file, line, func, name);
-			return res;
-		}
-	}
-#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-
-	ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock);
-	res = pthread_rwlock_wrlock(lock);
-	if (!res)
-		ast_mark_lock_acquired(lock);
-	else
-		ast_remove_lock_info(lock);
-	return res;
-}
-
-
-static inline int _ast_rwlock_tryrdlock(ast_rwlock_t *lock, const char *name,
-	const char *file, int line, const char *func)
-{
-	int res;
-#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
-	int canlog = strcmp(file, "logger.c");
-	
-	if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
-		 /* Don't warn abount uninitialized lock.
-		  * Simple try to initialize it.
-		  * May be not needed in linux system.
-		  */
-		res = __ast_rwlock_init(file, line, func, name, lock);
-		if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
-			__ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
-					file, line, func, name);
-			return res;
-		}
-	}
-#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-
-	ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock);
-	res = pthread_rwlock_tryrdlock(lock);
-	if (!res)
-		ast_mark_lock_acquired(lock);
-	else
-		ast_remove_lock_info(lock);
-	return res;
-}
-
-
-static inline int _ast_rwlock_trywrlock(ast_rwlock_t *lock, const char *name,
-	const char *file, int line, const char *func)
-{
-	int res;
-#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
-	int canlog = strcmp(file, "logger.c");
-	
-	if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
-		 /* Don't warn abount uninitialized lock.
-		  * Simple try to initialize it.
-		  * May be not needed in linux system.
-		  */
-		res = __ast_rwlock_init(file, line, func, name, lock);
-		if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
-			__ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
-					file, line, func, name);
-			return res;
-		}
-	}
-#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-
-	ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock);
-	res = pthread_rwlock_trywrlock(lock);
-	if (!res)
-		ast_mark_lock_acquired(lock);
-	else
-		ast_remove_lock_info(lock);
-	return res;
-}
-
-#else /* !DEBUG_THREADS */
-
-static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
-{
-	int res;
-	pthread_rwlockattr_t attr;
-
-	pthread_rwlockattr_init(&attr);
-
-#ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
-	pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
-#endif
-
-	res = pthread_rwlock_init(prwlock, &attr);
-	pthread_rwlockattr_destroy(&attr);
-	return res;
-}
-
-static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
-{
-	return pthread_rwlock_destroy(prwlock);
-}
-
-static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
-{
-	return pthread_rwlock_unlock(prwlock);
-}
-
-static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
-{
-	return pthread_rwlock_rdlock(prwlock);
-}
-
-static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
-{
-	return pthread_rwlock_tryrdlock(prwlock);
-}
-
-static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
-{
-	return pthread_rwlock_wrlock(prwlock);
-}
-
-static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
-{
-	return pthread_rwlock_trywrlock(prwlock);
-}
-#endif /* !DEBUG_THREADS */
-
 /* Statically declared read/write locks */
 
 #ifndef HAVE_PTHREAD_RWLOCK_INITIALIZER

Modified: trunk/include/asterisk/logger.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/logger.h?view=diff&rev=118173&r1=118172&r2=118173
==============================================================================
--- trunk/include/asterisk/logger.h (original)
+++ trunk/include/asterisk/logger.h Fri May 23 17:35:50 2008
@@ -219,6 +219,50 @@
 	} \
 } while (0)
 
+#ifndef _LOGGER_BACKTRACE_H
+#define _LOGGER_BACKTRACE_H
+#ifdef HAVE_BKTR
+#define AST_MAX_BT_FRAMES 32
+/* \brief
+ *
+ * A structure to hold backtrace information. This structure provides an easy means to 
+ * store backtrace information or pass backtraces to other functions.
+ */
+struct ast_bt {
+	/*! The addresses of the stack frames. This is filled in by calling the glibc backtrace() function */
+	void *addresses[AST_MAX_BT_FRAMES];
+	/*! The number of stack frames in the backtrace */
+	int num_frames;
+	/*! Tells if the ast_bt structure was dynamically allocated */
+	unsigned int alloced:1;
+};
+
+/* \brief
+ * Allocates memory for an ast_bt and stores addresses and symbols.
+ *
+ * \return Returns NULL on failure, or the allocated ast_bt on success
+ */
+struct ast_bt *ast_bt_create(void);
+
+/* \brief
+ * Fill an allocated ast_bt with addresses
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_bt_get_addresses(struct ast_bt *bt);
+
+/* \brief
+ * 
+ * Free dynamically allocated portions of an ast_bt
+ *
+ * \retval NULL.
+ */
+void *ast_bt_destroy(struct ast_bt *bt);
+
+#endif /* HAVE_BKTR */
+#endif /* _LOGGER_BACKTRACE_H */
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: trunk/main/logger.c
URL: http://svn.digium.com/view/asterisk/trunk/main/logger.c?view=diff&rev=118173&r1=118172&r2=118173
==============================================================================
--- trunk/main/logger.c (original)
+++ trunk/main/logger.c Fri May 23 17:35:50 2008
@@ -1127,30 +1127,67 @@
 	return;
 }
 
+#ifdef HAVE_BKTR
+
+struct ast_bt *ast_bt_create(void) 
+{
+	struct ast_bt *bt = ast_calloc(1, sizeof(*bt));
+	if (!bt) {
+		ast_log(LOG_ERROR, "Unable to allocate memory for backtrace structure!\n");
+		return NULL;
+	}
+
+	bt->alloced = 1;
+
+	ast_bt_get_addresses(bt);
+
+	return bt;
+}
+
+int ast_bt_get_addresses(struct ast_bt *bt)
+{
+	bt->num_frames = backtrace(bt->addresses, AST_MAX_BT_FRAMES);
+
+	return 0;
+}
+
+void *ast_bt_destroy(struct ast_bt *bt)
+{
+	if (bt->alloced) {
+		ast_free(bt);
+	}
+
+	return NULL;
+}
+
+#endif /* HAVE_BKTR */
+
 void ast_backtrace(void)
 {
 #ifdef HAVE_BKTR
-	int count = 0, i = 0;
-	void **addresses;
+	struct ast_bt *backtrace;
+	int i = 0;
 	char **strings;
 
-	if ((addresses = ast_calloc(MAX_BACKTRACE_FRAMES, sizeof(*addresses)))) {
-		count = backtrace(addresses, MAX_BACKTRACE_FRAMES);
-		if ((strings = backtrace_symbols(addresses, count))) {
-			ast_debug(1, "Got %d backtrace record%c\n", count, count != 1 ? 's' : ' ');
-			for (i = 0; i < count; i++) {
+	if (!(backtrace = ast_bt_create())) {
+		ast_log(LOG_WARNING, "Unable to allocate space for backtrace structure\n");
+		return;
+	}
+
+	if ((strings = backtrace_symbols(backtrace->addresses, backtrace->num_frames))) {
+		ast_debug(1, "Got %d backtrace record%c\n", backtrace->num_frames, backtrace->num_frames != 1 ? 's' : ' ');
+		for (i = 0; i < backtrace->num_frames; i++) {
 #if __WORDSIZE == 32
-				ast_log(LOG_DEBUG, "#%d: [%08X] %s\n", i, (unsigned int)addresses[i], strings[i]);
+			ast_log(LOG_DEBUG, "#%d: [%08X] %s\n", i, (unsigned int)backtrace->addresses[i], strings[i]);
 #elif __WORDSIZE == 64
-				ast_log(LOG_DEBUG, "#%d: [%016lX] %s\n", i, (unsigned long)addresses[i], strings[i]);
+			ast_log(LOG_DEBUG, "#%d: [%016lX] %s\n", i, (unsigned long)backtrace->addresses[i], strings[i]);
 #endif
-			}
-			free(strings);
-		} else {
-			ast_debug(1, "Could not allocate memory for backtrace\n");
-		}
-		ast_free(addresses);
-	}
+		}
+		free(strings);
+	} else {
+		ast_debug(1, "Could not allocate memory for backtrace\n");
+	}
+	ast_bt_destroy(backtrace);
 #else
 	ast_log(LOG_WARNING, "Must run configure with '--with-execinfo' for stack backtraces.\n");
 #endif

Modified: trunk/main/utils.c
URL: http://svn.digium.com/view/asterisk/trunk/main/utils.c?view=diff&rev=118173&r1=118172&r2=118173
==============================================================================
--- trunk/main/utils.c (original)
+++ trunk/main/utils.c Fri May 23 17:35:50 2008
@@ -540,6 +540,9 @@
 		enum ast_lock_type type;
 		/*! This thread is waiting on this lock */
 		int pending:2;
+#ifdef HAVE_BKTR
+		struct ast_bt *backtrace;
+#endif
 	} locks[AST_MAX_LOCKS];
 	/*! This is the number of locks currently held by this thread.
 	 *  The index (num_locks - 1) has the info on the last one in the
@@ -583,9 +586,13 @@
  * \brief The thread storage key for per-thread lock info
  */
 AST_THREADSTORAGE_CUSTOM(thread_lock_info, NULL, lock_info_destroy);
-
+#ifdef HAVE_BKTR
+void ast_store_lock_info(enum ast_lock_type type, const char *filename,
+	int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
+#else
 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
 	int line_num, const char *func, const char *lock_name, void *lock_addr)
+#endif
 {
 	struct thr_lock_info *lock_info;
 	int i;
@@ -598,6 +605,9 @@
 	for (i = 0; i < lock_info->num_locks; i++) {
 		if (lock_info->locks[i].lock_addr == lock_addr) {
 			lock_info->locks[i].times_locked++;
+#ifdef HAVE_BKTR
+			lock_info->locks[i].backtrace = bt;
+#endif
 			pthread_mutex_unlock(&lock_info->lock);
 			return;
 		}
@@ -628,6 +638,9 @@
 	lock_info->locks[i].times_locked = 1;
 	lock_info->locks[i].type = type;
 	lock_info->locks[i].pending = 1;
+#ifdef HAVE_BKTR
+	lock_info->locks[i].backtrace = bt;
+#endif
 	lock_info->num_locks++;
 
 	pthread_mutex_unlock(&lock_info->lock);
@@ -661,8 +674,11 @@
 	}
 	pthread_mutex_unlock(&lock_info->lock);
 }
-
+#ifdef HAVE_BKTR
+void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
+#else
 void ast_remove_lock_info(void *lock_addr)
+#endif
 {
 	struct thr_lock_info *lock_info;
 	int i = 0;
@@ -685,6 +701,9 @@
 
 	if (lock_info->locks[i].times_locked > 1) {
 		lock_info->locks[i].times_locked--;
+#ifdef HAVE_BKTR
+		lock_info->locks[i].backtrace = bt;
+#endif
 		pthread_mutex_unlock(&lock_info->lock);
 		return;
 	}
@@ -713,6 +732,30 @@
 
 	return "UNKNOWN";
 }
+
+#ifdef HAVE_BKTR
+static void append_backtrace_information(struct ast_str **str, struct ast_bt *bt)
+{
+	char **symbols;
+
+	if (!bt) {
+		ast_str_append(str, 0, "\tNo backtrace to print\n");
+		return;
+	}
+
+	if ((symbols = backtrace_symbols(bt->addresses, bt->num_frames))) {
+		int frame_iterator;
+		
+		for (frame_iterator = 0; frame_iterator < bt->num_frames; ++frame_iterator) {
+			ast_str_append(str, 0, "\t%s\n", symbols[frame_iterator]);
+		}
+
+		free(symbols);
+	} else {
+		ast_str_append(str, 0, "\tCouldn't retrieve backtrace symbols\n");
+	}
+}
+#endif
 
 static void append_lock_information(struct ast_str **str, struct thr_lock_info *lock_info, int i)
 {
@@ -728,6 +771,9 @@
 				   lock_info->locks[i].func, lock_info->locks[i].lock_name,
 				   lock_info->locks[i].lock_addr, 
 				   lock_info->locks[i].times_locked);
+#ifdef HAVE_BKTR
+	append_backtrace_information(str, lock_info->locks[i].backtrace);
+#endif
 	
 	if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1)
 		return;

Modified: trunk/utils/ael_main.c
URL: http://svn.digium.com/view/asterisk/trunk/utils/ael_main.c?view=diff&rev=118173&r1=118172&r2=118173
==============================================================================
--- trunk/utils/ael_main.c (original)
+++ trunk/utils/ael_main.c Fri May 23 17:35:50 2008
@@ -578,7 +578,16 @@
 void ast_mark_lock_acquired(void *lock_addr)
 {
 }
-
+#ifdef HAVE_BKTR
+void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
+{
+}
+
+void ast_store_lock_info(enum ast_lock_type type, const char *filename,
+	int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
+{
+}
+#else

[... 182 lines stripped ...]



More information about the asterisk-commits mailing list