diff options
author | Richard Mudgett <rmudgett@digium.com> | 2014-12-12 23:49:36 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2014-12-12 23:49:36 +0000 |
commit | 308c1b41dd5e8d89c2950230c1babd826b006629 (patch) | |
tree | a130bf67a6080b7c8f7774913289256e230f7d21 /include/asterisk/lock.h | |
parent | 901221ffaeae53bf95671261eef405f955cf1d54 (diff) |
DEBUG_THREADS: Fix regression and lock tracking initialization problems.
This patch started with David Lee's patch at
https://reviewboard.asterisk.org/r/2826/ and includes a regression fix
introduced by the ASTERISK-22455 patch.
The initialization of a mutex's lock tracking structure was not protected
in a critical section. This is fine for any mutex that is explicitly
initialized, but a static mutex may have its lock tracking double
initialized if multiple threads attempt the first lock simultaneously.
* Added a global mutex to properly serialize initialization of the lock
tracking structure. The painful global lock can be mitigated by adding a
double checked lock flag as discussed on the original review request.
* Defer lock tracking initialization until first use.
* Don't be "helpful" and initialize an uninitialized lock when
DEBUG_THREADS is enabled. Debug code is not supposed to fix or change
normal code behavior. We don't need a lock initialization race that would
force a re-setup of lock tracking. Lock tracking already handles
initialization on first use.
* Properly handle allocation failures of the lock tracking structure.
* No need to initialize tracking data in __ast_pthread_mutex_destroy()
just to turn around and destroy it.
The regression introduced by ASTERISK-22455 is the result of manipulating
a pthread_mutex_t struct outside of the pthread library code. The
pthread_mutex_t struct seems to have a global linked list pointer member
that can get changed by other threads. Therefore, saving and restoring
the contents of a pthread_mutex_t struct is a bad thing.
Thanks to Thomas Airmont for finding this obscure regression.
* Don't overwrite the struct ast_lock_track.reentr_mutex member to restore
tracking data in __ast_cond_wait() and __ast_cond_timedwait(). The
pthread_mutex_t struct must be treated as a read-only opaque variable.
Miscellaneous other items fixed by this patch:
* Match ast_suspend_lock_info() with ast_restore_lock_info() in
__ast_cond_timedwait().
* Made some uninitialized lock sanity checks return EINVAL and try a
DO_THREAD_CRASH.
* Fix bad canlog initialization expressions.
ASTERISK-24614 #close
Reported by: Thomas Airmont
Review: https://reviewboard.asterisk.org/r/4247/
Review: https://reviewboard.asterisk.org/r/2826/
........
Merged revisions 429539 from http://svn.asterisk.org/svn/asterisk/branches/11
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@429541 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'include/asterisk/lock.h')
-rw-r--r-- | include/asterisk/lock.h | 47 |
1 files changed, 7 insertions, 40 deletions
diff --git a/include/asterisk/lock.h b/include/asterisk/lock.h index 7741654a0..5e651600e 100644 --- a/include/asterisk/lock.h +++ b/include/asterisk/lock.h @@ -18,7 +18,7 @@ /*! \file * \brief Asterisk locking-related definitions: - * - ast_mutext_t, ast_rwlock_t and related functions; + * - ast_mutex_t, ast_rwlock_t and related functions; * - atomic arithmetic instructions; * - wrappers for channel locking. * @@ -102,6 +102,12 @@ struct ast_channel; +/*! + * \brief Lock tracking information. + * + * \note Any changes to this struct MUST be reflected in the + * lock.c:restore_lock_tracking() function. + */ struct ast_lock_track { const char *file[AST_MAX_REENTRANCY]; int lineno[AST_MAX_REENTRANCY]; @@ -474,45 +480,6 @@ static inline void ast_reentrancy_unlock(struct ast_lock_track *lt) } } -static inline void ast_reentrancy_init(struct ast_lock_track **plt) -{ - int i; - pthread_mutexattr_t reentr_attr; - struct ast_lock_track *lt = *plt; - - if (!lt) { - lt = *plt = (struct ast_lock_track *) calloc(1, sizeof(*lt)); - } - - for (i = 0; i < AST_MAX_REENTRANCY; i++) { - lt->file[i] = NULL; - lt->lineno[i] = 0; - lt->func[i] = NULL; - lt->thread[i] = 0; -#ifdef HAVE_BKTR - memset(<->backtrace[i], 0, sizeof(lt->backtrace[i])); -#endif - } - - lt->reentrancy = 0; - - pthread_mutexattr_init(&reentr_attr); - pthread_mutexattr_settype(&reentr_attr, AST_MUTEX_KIND); - pthread_mutex_init(<->reentr_mutex, &reentr_attr); - pthread_mutexattr_destroy(&reentr_attr); -} - -static inline void delete_reentrancy_cs(struct ast_lock_track **plt) -{ - struct ast_lock_track *lt; - if (*plt) { - lt = *plt; - pthread_mutex_destroy(<->reentr_mutex); - free(lt); - *plt = NULL; - } -} - #else /* !DEBUG_THREADS */ #define AO2_DEADLOCK_AVOIDANCE(obj) \ |