[asterisk-commits] russell: trunk r105410 - in /trunk: ./ main/autoservice.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Feb 29 17:36:46 CST 2008
Author: russell
Date: Fri Feb 29 17:36:46 2008
New Revision: 105410
URL: http://svn.digium.com/view/asterisk?view=rev&rev=105410
Log:
Merged revisions 105409 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r105409 | russell | 2008-02-29 17:34:32 -0600 (Fri, 29 Feb 2008) | 23 lines
Fix a major bug in autoservice. There was a race condition in the handling of
the list of channels in autoservice. The problem was that it was possible for
a channel to get removed from autoservice and destroyed, while the autoservice
was still messing with the channel. This led to memory corruption, and caused
crashes. This explains multiple backtraces I have seen that have references
to autoservice, but do to the nature of the issue (memory corruption), could
cause crashes in a number of areas.
(fixes the crash in BE-386)
(closes issue #11694)
(closes issue #11940)
The following issues could be related. If you are the reporter of one of these,
please update to include this fix and try again.
(potentially fixes issue #11189)
(potentially fixes issue #12107)
(potentially fixes issue #11573)
(potentially fixes issue #12008)
(potentially fixes issue #11189)
(potentially fixes issue #11993)
(potentially fixes issue #11791)
........
Modified:
trunk/ (props changed)
trunk/main/autoservice.c
Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.
Modified: trunk/main/autoservice.c
URL: http://svn.digium.com/view/asterisk/trunk/main/autoservice.c?view=diff&rev=105410&r1=105409&r2=105410
==============================================================================
--- trunk/main/autoservice.c (original)
+++ trunk/main/autoservice.c Fri Feb 29 17:36:46 2008
@@ -60,6 +60,8 @@
static pthread_t asthread = AST_PTHREADT_NULL;
+static int as_chan_list_state;
+
static void defer_frame(struct ast_channel *chan, struct ast_frame *f)
{
struct ast_frame *dup_f;
@@ -83,6 +85,11 @@
int x = 0, ms = 500;
AST_RWLIST_RDLOCK(&aslist);
+
+ /* At this point, we know that no channels that have been removed are going
+ * to get used again. */
+ as_chan_list_state++;
+
AST_RWLIST_TRAVERSE(&aslist, as, list) {
if (!ast_check_hangup(as->chan)) {
if (x < MAX_AUTOMONS)
@@ -207,10 +214,18 @@
struct ast_frame *f;
int removed = 0;
int orig_end_dtmf_flag = 0;
+ int chan_list_state;
AST_LIST_HEAD_INIT_NOLOCK(&dtmf_frames);
AST_RWLIST_WRLOCK(&aslist);
+
+ /* Save the autoservice channel list state. We _must_ verify that the channel
+ * list has been rebuilt before we return. Because, after we return, the channel
+ * could get destroyed and we don't want our poor autoservice thread to step on
+ * it after its gone! */
+ chan_list_state = as_chan_list_state;
+
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&aslist, as, list) {
if (as->chan == chan) {
AST_RWLIST_REMOVE_CURRENT(list);
@@ -248,5 +263,8 @@
ast_frfree(f);
}
+ while (chan_list_state == as_chan_list_state)
+ usleep(1000);
+
return res;
}
More information about the asterisk-commits
mailing list