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/branches/1.4@67716 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.4
Russell Bryant 18 years ago
parent 1f6872a45e
commit e7dd69eea8

@ -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

@ -1176,7 +1176,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);

Loading…
Cancel
Save