mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-04 03:50:31 +00:00
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/branches/13@429540 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -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) \
|
||||
|
594
main/lock.c
594
main/lock.c
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user