Merged revisions 67716 via svnmerge from

https://origsvn.digium.com/svn/asterisk/branches/1.4

................
r67716 | russell | 2007-06-06 11:55:59 -0500 (Wed, 06 Jun 2007) | 13 lines

Merged revisions 67715 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.2

........
r67715 | russell | 2007-06-06 11:40:51 -0500 (Wed, 06 Jun 2007) | 5 lines

We have some bug reports showing crashes due to a double free of a channel.
Add a sanity check to ast_channel_free() to make sure we don't go on trying
to free a channel that wasn't found in the channel list.
(issue #8850, and others...)

........

................


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@67717 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Russell Bryant
2007-06-06 16:58:28 +00:00
parent 6ddcfff1c7
commit 18101ff0e3
2 changed files with 11 additions and 4 deletions

View File

@@ -729,8 +729,10 @@ struct { \
used to link entries of this list together. used to link entries of this list together.
\warning The removed entry is \b not freed nor modified in any way. \warning The removed entry is \b not freed nor modified in any way.
*/ */
#define AST_LIST_REMOVE(head, elm, field) do { \ #define AST_LIST_REMOVE(head, elm, field) ({ \
__typeof(elm) __res = NULL; \
if ((head)->first == (elm)) { \ if ((head)->first == (elm)) { \
__res = (head)->first; \
(head)->first = (elm)->field.next; \ (head)->first = (elm)->field.next; \
if ((head)->last == (elm)) \ if ((head)->last == (elm)) \
(head)->last = NULL; \ (head)->last = NULL; \
@@ -739,13 +741,15 @@ struct { \
while (curelm && (curelm->field.next != (elm))) \ while (curelm && (curelm->field.next != (elm))) \
curelm = curelm->field.next; \ curelm = curelm->field.next; \
if (curelm) { \ if (curelm) { \
__res = curelm; \
curelm->field.next = (elm)->field.next; \ curelm->field.next = (elm)->field.next; \
if ((head)->last == (elm)) \ if ((head)->last == (elm)) \
(head)->last = curelm; \ (head)->last = curelm; \
} \ } \
} \ } \
(elm)->field.next = NULL; \ (elm)->field.next = NULL; \
} while (0) (__res); \
})
#define AST_RWLIST_REMOVE AST_LIST_REMOVE #define AST_RWLIST_REMOVE AST_LIST_REMOVE

View File

@@ -1082,7 +1082,10 @@ void ast_channel_free(struct ast_channel *chan)
headp=&chan->varshead; headp=&chan->varshead;
AST_LIST_LOCK(&channels); AST_LIST_LOCK(&channels);
AST_LIST_REMOVE(&channels, chan, chan_list); if (!AST_LIST_REMOVE(&channels, chan, chan_list)) {
AST_LIST_UNLOCK(&channels);
ast_log(LOG_ERROR, "Unable to find channel in list to free. Assuming it has already been done.\n");
}
/* Lock and unlock the channel just to be sure nobody /* Lock and unlock the channel just to be sure nobody
has it locked still */ has it locked still */
ast_channel_lock(chan); ast_channel_lock(chan);