Fix a bug in the rwlock tracking. ast_rwlock_unlock did not take into
authorMark Michelson <mmichelson@digium.com>
Wed, 25 Jun 2008 22:25:20 +0000 (22:25 +0000)
committerMark Michelson <mmichelson@digium.com>
Wed, 25 Jun 2008 22:25:20 +0000 (22:25 +0000)
account that multiple threads could hold the same rdlock at the same time.
As such, it expected that when a thread released a lock that it must have
been the last to acquire the lock as well. Erroneous error messages would
be sent to the console stating that a thread was attempting to unlock a lock
it did not own.

Now all threads are examined to be sure that the message is only printed
when it is supposed to be printed.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@125133 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/lock.h

index 4122978..f97b3f9 100644 (file)
@@ -1048,15 +1048,31 @@ static inline int _ast_rwlock_unlock(ast_rwlock_t *t, const char *name,
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
        
        ast_reentrancy_lock(lt);
-       if (lt->reentrancy && (lt->thread[lt->reentrancy-1] != pthread_self())) {
-               __ast_mutex_logger("%s line %d (%s): attempted unlock rwlock '%s' without owning it!\n",
-                                       filename, line, func, name);
-               __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
-                               lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], name);
+       if (lt->reentrancy) {
+               int lock_found = 0;
+               int i;
+               for (i = lt->reentrancy-1; i >= 0; --i) {
+                       if (lt->thread[i] == pthread_self()) {
+                               lock_found = 1;
+                               if (i != lt->reentrancy-1) {
+                                       lt->file[i] = lt->file[lt->reentrancy-1];
+                                       lt->lineno[i] = lt->lineno[lt->reentrancy-1];
+                                       lt->func[i] = lt->func[lt->reentrancy-1];
+                                       lt->thread[i] = lt->thread[lt->reentrancy-1];
+                               }
+                               break;
+                       }
+               }
+               if (!lock_found) {
+                       __ast_mutex_logger("%s line %d (%s): attempted unlock rwlock '%s' without owning it!\n",
+                                               filename, line, func, name);
+                       __ast_mutex_logger("%s line %d (%s): '%s' was last locked here.\n",
+                                       lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], name);
 #ifdef HAVE_BKTR
                __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
 #endif
                DO_THREAD_CRASH;
+               }
        }
 
        if (--lt->reentrancy < 0) {
@@ -1065,13 +1081,6 @@ static inline int _ast_rwlock_unlock(ast_rwlock_t *t, const char *name,
                lt->reentrancy = 0;
        }
 
-       if (lt->reentrancy < AST_MAX_REENTRANCY) {
-               lt->file[lt->reentrancy] = NULL;
-               lt->lineno[lt->reentrancy] = 0;
-               lt->func[lt->reentrancy] = NULL;
-               lt->thread[lt->reentrancy] = 0;
-       }
-
 #ifdef HAVE_BKTR
        if (lt->reentrancy) {
                bt = &lt->backtrace[lt->reentrancy - 1];