[asterisk-commits] tilghman: branch 1.4 r187428 - in /branches/1.4: include/asterisk/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Apr 9 13:08:25 CDT 2009


Author: tilghman
Date: Thu Apr  9 13:08:20 2009
New Revision: 187428

URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=187428
Log:
Race condition between ast_cli_command() and 'module unload' could cause a deadlock.
Add lock timeouts to avoid this potential deadlock.
(closes issue #14705)
 Reported by: jamessan
 Patches: 
       20090320__bug14705.diff.txt uploaded by tilghman (license 14)
 Tested by: jamessan

Modified:
    branches/1.4/include/asterisk/lock.h
    branches/1.4/main/manager.c

Modified: branches/1.4/include/asterisk/lock.h
URL: http://svn.digium.com/svn-view/asterisk/branches/1.4/include/asterisk/lock.h?view=diff&rev=187428&r1=187427&r2=187428
==============================================================================
--- branches/1.4/include/asterisk/lock.h (original)
+++ branches/1.4/include/asterisk/lock.h Thu Apr  9 13:08:20 2009
@@ -993,11 +993,11 @@
 	return res;
 }
 
-#define ast_rwlock_tryrdlock(a) \
-	_ast_rwlock_tryrdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-static inline int _ast_rwlock_tryrdlock(ast_rwlock_t *lock, const char *name,
-	const char *file, int line, const char *func)
+#define ast_rwlock_timedrdlock(a,b) \
+	_ast_rwlock_timedrdlock(a, # a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+static inline int _ast_rwlock_rdlock(ast_rwlock_t *lock, const char *name,
+	const struct timespec *abs_timeout, const char *file, int line, const char *func)
 {
 	int res;
 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
@@ -1016,9 +1016,9 @@
 		}
 	}
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
-
+	
 	ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock);
-	res = pthread_rwlock_tryrdlock(lock);
+	res = pthread_rwlock_timedrdlock(lock, abs_timeout);
 	if (!res)
 		ast_mark_lock_acquired(lock);
 	else
@@ -1026,11 +1026,11 @@
 	return res;
 }
 
-#define ast_rwlock_trywrlock(a) \
-	_ast_rwlock_trywrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-static inline int _ast_rwlock_trywrlock(ast_rwlock_t *lock, const char *name,
-	const char *file, int line, const char *func)
+#define ast_rwlock_timedwrlock(a,b) \
+	_ast_rwlock_timedwrlock(a, # a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+static inline int _ast_rwlock_timedwrlock(ast_rwlock_t *lock, const char *name,
+	const struct timespec *abs_timeout, const char *file, int line, const char *func)
 {
 	int res;
 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
@@ -1051,6 +1051,72 @@
 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
 
 	ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock);
+	res = pthread_rwlock_timedwrlock(lock, abs_timeout);
+	if (!res)
+		ast_mark_lock_acquired(lock);
+	else
+		ast_remove_lock_info(lock);
+	return res;
+}
+
+#define ast_rwlock_tryrdlock(a) \
+	_ast_rwlock_tryrdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+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;
+}
+
+#define ast_rwlock_trywrlock(a) \
+	_ast_rwlock_trywrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+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);
@@ -1092,6 +1158,11 @@
 	return pthread_rwlock_rdlock(prwlock);
 }
 
+static inline int ast_rwlock_timedrdlock(ast_rwlock_t *prwlock, const struct timespec *abs_timeout)
+{
+	return pthread_rwlock_timedrdlock(prwlock, abs_timeout);
+}
+
 static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
 {
 	return pthread_rwlock_tryrdlock(prwlock);
@@ -1100,6 +1171,11 @@
 static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
 {
 	return pthread_rwlock_wrlock(prwlock);
+}
+
+static inline int ast_rwlock_timedwrlock(ast_rwlock_t *prwlock, const struct timespec *abs_timeout)
+{
+	return pthread_rwlock_timedwrlock(prwlock, abs_timeout);
 }
 
 static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)

Modified: branches/1.4/main/manager.c
URL: http://svn.digium.com/svn-view/asterisk/branches/1.4/main/manager.c?view=diff&rev=187428&r1=187427&r2=187428
==============================================================================
--- branches/1.4/main/manager.c (original)
+++ branches/1.4/main/manager.c Thu Apr  9 13:08:20 2009
@@ -2608,8 +2608,12 @@
 int ast_manager_unregister(char *action) 
 {
 	struct manager_action *cur, *prev;
-
-	ast_rwlock_wrlock(&actionlock);
+	struct timespec tv = { 5, };
+
+	if (ast_rwlock_timedwrlock(&actionlock, &tv)) {
+		ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
+		return -1;
+	}
 	cur = prev = first_action;
 	while (cur) {
 		if (!strcasecmp(action, cur->action)) {
@@ -2638,8 +2642,12 @@
 {
 	struct manager_action *cur, *prev = NULL;
 	int ret;
-
-	ast_rwlock_wrlock(&actionlock);
+	struct timespec tv = { 5, };
+
+	if (ast_rwlock_timedwrlock(&actionlock, &tv)) {
+		ast_log(LOG_ERROR, "Could not obtain lock on manager list\n");
+		return -1;
+	}
 	cur = first_action;
 	while (cur) { /* Walk the list of actions */
 		ret = strcasecmp(cur->action, act->action);
@@ -2693,7 +2701,10 @@
 	cur->description = description;
 	cur->next = NULL;
 
-	ast_manager_register_struct(cur);
+	if (ast_manager_register_struct(cur)) {
+		ast_free(cur);
+		return -1;
+	}
 
 	return 0;
 }




More information about the asterisk-commits mailing list