func_lock: Fix memory corruption during unload.
AST_TRAVERSE accessess current as current = current->(field).next ... and since we free current (and ast_free poisons the memory) we either end up on a ast_mutex_lock to a non-existing lock that can never be obtained, or a segfault. Incidentally add logging in the "we have to wait for a lock to release" case, and remove an ineffective statement that sets memory that was just cleared by ast_calloc to zero. Change-Id: Id19ba3d9867b23d0e6783b97e6ecd8e62698b8c3 Signed-off-by: Jaco Kroon <jaco@uls.co.za>
This commit is contained in:
parent
6bd741b77d
commit
a3df5d7de8
|
@ -249,7 +249,6 @@ static int get_lock(struct ast_channel *chan, char *lockname, int trylock)
|
|||
AST_LIST_UNLOCK(&locklist);
|
||||
return -1;
|
||||
}
|
||||
current->requesters = 0;
|
||||
AST_LIST_INSERT_TAIL(&locklist, current, entries);
|
||||
}
|
||||
/* Add to requester list */
|
||||
|
@ -449,9 +448,16 @@ static int unload_module(void)
|
|||
ast_custom_function_unregister(&trylock_function);
|
||||
|
||||
AST_LIST_LOCK(&locklist);
|
||||
AST_LIST_TRAVERSE(&locklist, current, entries) {
|
||||
while ((current = AST_LIST_REMOVE_HEAD(&locklist, entries))) {
|
||||
int warned = 0;
|
||||
ast_mutex_lock(¤t->mutex);
|
||||
while (current->owner || current->requesters) {
|
||||
if (!warned) {
|
||||
ast_log(LOG_WARNING, "Waiting for %d requesters for %s lock %s.\n",
|
||||
current->requesters, current->owner ? "locked" : "unlocked",
|
||||
current->name);
|
||||
warned = 1;
|
||||
}
|
||||
/* either the mutex is locked, or other parties are currently in get_lock,
|
||||
* we need to wait for all of those to clear first */
|
||||
ast_cond_wait(¤t->cond, ¤t->mutex);
|
||||
|
|
Loading…
Reference in New Issue