[asterisk-commits] murf: trunk r114520 - in /trunk: channels/chan_sip.c main/utils.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Apr 22 09:38:47 CDT 2008


Author: murf
Date: Tue Apr 22 09:38:46 2008
New Revision: 114520

URL: http://svn.digium.com/view/asterisk?view=rev&rev=114520
Log:

Hopefully, this will resolve the issues that russellb had with this log_show_lock().
I gathered the code that filled the string, and put it in a different func which
I cryptically call "append_lock_information()".
Now, both log_show_lock(), and handle_show_locks() both call this code to do
the work. Tested, seems to work fine. 
Also, log_show_lock was modified to use the ast_str stuff, along with checking
for successful ast_str creation, and freeing the ast_str obj when finished.
A break was inserted to terminate the search for the lock; we should never
see it twice.

An example usage in chan_sip.c was created as a comment, for instructional
purposes.


Modified:
    trunk/channels/chan_sip.c
    trunk/main/utils.c

Modified: trunk/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_sip.c?view=diff&rev=114520&r1=114519&r2=114520
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Tue Apr 22 09:38:46 2008
@@ -12927,8 +12927,10 @@
 	struct sip_pvt *dialog = dialogobj;
 	time_t *t = arg;
 	
+	/* log_show_lock(ao2_object_get_lockaddr(dialog)); this is an example of how to use log_show_lock() */
 	if (sip_pvt_trylock(dialog)) {
-		/* this path gets executed fairly frequently (3% or so) even in low load
+		/* In very short-duration calls via sipp,
+		   this path gets executed fairly frequently (3% or so) even in low load
 		   situations; the routines we most commonly fight for a lock with:
 		   sip_answer (7 out of 9)
 		   sip_hangup (2 out of 9)

Modified: trunk/main/utils.c
URL: http://svn.digium.com/view/asterisk/trunk/main/utils.c?view=diff&rev=114520&r1=114519&r2=114520
==============================================================================
--- trunk/main/utils.c (original)
+++ trunk/main/utils.c Tue Apr 22 09:38:46 2008
@@ -714,52 +714,86 @@
 	return "UNKNOWN";
 }
 
-/*! \todo this function is very broken and duplicates a lot of code ... */
+static void append_lock_information(struct ast_str **str, struct thr_lock_info *lock_info, int i)
+{
+	int j;
+	ast_mutex_t *lock;
+	
+	ast_str_append(str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d)\n", 
+				   lock_info->locks[i].pending > 0 ? "Waiting for " : 
+				   lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i,
+				   lock_info->locks[i].file, 
+				   locktype2str(lock_info->locks[i].type),
+				   lock_info->locks[i].line_num,
+				   lock_info->locks[i].func, lock_info->locks[i].lock_name,
+				   lock_info->locks[i].lock_addr, 
+				   lock_info->locks[i].times_locked);
+	
+	if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1)
+		return;
+	
+	/* We only have further details for mutexes right now */
+	if (lock_info->locks[i].type != AST_MUTEX)
+		return;
+	
+	lock = lock_info->locks[i].lock_addr;
+	
+	ast_reentrancy_lock(lock);
+	for (j = 0; *str && j < lock->reentrancy; j++) {
+		ast_str_append(str, 0, "=== --- ---> Locked Here: %s line %d (%s)\n",
+					   lock->file[j], lock->lineno[j], lock->func[j]);
+	}
+	ast_reentrancy_unlock(lock);	
+}
+
+
+/*! This function can help you find highly temporal locks; locks that happen for a 
+    short time, but at unexpected times, usually at times that create a deadlock,
+	Why is this thing locked right then? Who is locking it? Who am I fighting
+    with for this lock? 
+
+	To answer such questions, just call this routine before you would normally try
+	to aquire a lock. It doesn't do anything if the lock is not acquired. If the
+	lock is taken, it will publish a line or two to the console via ast_log().
+
+	Sometimes, the lock message is pretty uninformative. For instance, you might
+	find that the lock is being aquired deep within the astobj2 code; this tells
+	you little about higher level routines that call the astobj2 routines.
+	But, using gdb, you can set a break at the ast_log below, and for that
+	breakpoint, you can set the commands:
+	  where
+	  cont
+	which will give a stack trace and continue. -- that aught to do the job!
+
+*/
 void log_show_lock(void *this_lock_addr)
 {
 	struct thr_lock_info *lock_info;
-	struct ast_str *str = NULL;
+	struct ast_str *str;
+
+	if (!(str = ast_str_create(4096))) {
+		ast_log(LOG_NOTICE,"Could not create str\n");
+		return;
+	}
+	
 
 	pthread_mutex_lock(&lock_infos_lock.mutex);
 	AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
 		int i;
 		pthread_mutex_lock(&lock_info->lock);
 		for (i = 0; str && i < lock_info->num_locks; i++) {
-			int j;
-			ast_mutex_t *lock;
+			/* ONLY show info about this particular lock, if
+			   it's acquired... */
 			if (lock_info->locks[i].lock_addr == this_lock_addr) {
-				
-				ast_log(LOG_NOTICE, "---> %sLock #%d (%s): %s %d %s %s %p (%d)\n", 
-						lock_info->locks[i].pending > 0 ? "Waiting for " : lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", 
-						i,
-						lock_info->locks[i].file, 
-						locktype2str(lock_info->locks[i].type),
-						lock_info->locks[i].line_num,
-						lock_info->locks[i].func, 
-						lock_info->locks[i].lock_name,
-						lock_info->locks[i].lock_addr, 
-						lock_info->locks[i].times_locked);
-				
-				if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1)
-					continue;
-				
-				/* We only have further details for mutexes right now */
-				if (lock_info->locks[i].type != AST_MUTEX)
-					continue;
-				
-				lock = lock_info->locks[i].lock_addr;
-				
-				ast_reentrancy_lock(lock);
-				for (j = 0; str && j < lock->reentrancy; j++) {
-					ast_log(LOG_NOTICE, "--- ---> Locked Here: %s line %d (%s)\n",
-								   lock->file[j], lock->lineno[j], lock->func[j]);
-				}
-				ast_reentrancy_unlock(lock);	
+				append_lock_information(&str, lock_info, i);
+				ast_log(LOG_NOTICE, "%s", str->str);
+				break;
 			}
 		}
 		pthread_mutex_unlock(&lock_info->lock);
 	}
 	pthread_mutex_unlock(&lock_infos_lock.mutex);
+	ast_free(str);
 }
 
 
@@ -802,34 +836,7 @@
 			lock_info->thread_name);
 		pthread_mutex_lock(&lock_info->lock);
 		for (i = 0; str && i < lock_info->num_locks; i++) {
-			int j;
-			ast_mutex_t *lock;
-
-			ast_str_append(&str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d)\n", 
-				lock_info->locks[i].pending > 0 ? "Waiting for " : 
-					lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i,
-				lock_info->locks[i].file, 
-				locktype2str(lock_info->locks[i].type),
-				lock_info->locks[i].line_num,
-				lock_info->locks[i].func, lock_info->locks[i].lock_name,
-				lock_info->locks[i].lock_addr, 
-				lock_info->locks[i].times_locked);
-
-			if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1)
-				continue;
-
-			/* We only have further details for mutexes right now */
-			if (lock_info->locks[i].type != AST_MUTEX)
-				continue;
-
-			lock = lock_info->locks[i].lock_addr;
-
-			ast_reentrancy_lock(lock);
-			for (j = 0; str && j < lock->reentrancy; j++) {
-				ast_str_append(&str, 0, "=== --- ---> Locked Here: %s line %d (%s)\n",
-					lock->file[j], lock->lineno[j], lock->func[j]);
-			}
-			ast_reentrancy_unlock(lock);	
+			append_lock_information(&str, lock_info, i);
 		}
 		pthread_mutex_unlock(&lock_info->lock);
 		if (!str)




More information about the asterisk-commits mailing list