]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 218430 via svnmerge from
authorJeff Peeler <jpeeler@digium.com>
Mon, 14 Sep 2009 22:49:25 +0000 (22:49 +0000)
committerJeff Peeler <jpeeler@digium.com>
Mon, 14 Sep 2009 22:49:25 +0000 (22:49 +0000)
https://origsvn.digium.com/svn/asterisk/trunk

................
  r218430 | jpeeler | 2009-09-14 17:38:25 -0500 (Mon, 14 Sep 2009) | 18 lines

  Merged revisions 218401 via svnmerge from
  https://origsvn.digium.com/svn/asterisk/branches/1.4

  ........
    r218401 | jpeeler | 2009-09-14 16:47:11 -0500 (Mon, 14 Sep 2009) | 11 lines

    Fix handling of DAHDI_EVENT_REMOVED event to prevent crash in do_monitor.

    After talking to rmudgett about some of his recent iflist locking changes, it
    was determined that the only place that would destroy a channel without being
    explicitly to do so was in handle_init_event. The loop to walk the interface
    list has been modified to wait to destroy the channel until the dahdi_pvt of
    the channel to be destroyed is no longer needed.

    (closes issue #15378)
    Reported by: samy
  ........
................

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.6.0@218431 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_dahdi.c

index 8a2914b496eb43572f81ab7a120eb0eec0d70c22..a140caf205ed42ff9568e5fa7ac78cc62822c85f 100644 (file)
@@ -7891,7 +7891,7 @@ static int dahdi_destroy_channel_bynum(int channel)
        return RESULT_FAILURE;
 }
 
-static int handle_init_event(struct dahdi_pvt *i, int event)
+static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
 {
        int res;
        pthread_t threadid;
@@ -7993,7 +7993,7 @@ static int handle_init_event(struct dahdi_pvt *i, int event)
                        res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
                        if (res < 0)
                                        ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
-                       return -1;
+                       return NULL;
                }
                break;
        case DAHDI_EVENT_NOALARM:
@@ -8058,7 +8058,7 @@ static int handle_init_event(struct dahdi_pvt *i, int event)
                default:
                        ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
                        res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
-                       return -1;
+                       return NULL;
                }
                break;
        case DAHDI_EVENT_POLARITY:
@@ -8089,12 +8089,11 @@ static int handle_init_event(struct dahdi_pvt *i, int event)
                                "interface %d\n", i->channel);
                }
                break;
-       case DAHDI_EVENT_REMOVED: /* destroy channel */
+       case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
                ast_log(LOG_NOTICE, 
                                "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
                                i->channel);
-               dahdi_destroy_channel_bynum(i->channel);
-               break;
+               return i;
        case DAHDI_EVENT_NEONMWI_ACTIVE:
                if (i->mwimonitor_neon) {
                        notify_message(i->mailbox, 1);
@@ -8108,7 +8107,7 @@ static int handle_init_event(struct dahdi_pvt *i, int event)
                }
                break;
        }
-       return 0;
+       return NULL;
 }
 
 static void *do_monitor(void *data)
@@ -8116,6 +8115,7 @@ static void *do_monitor(void *data)
        int count, res, res2, spoint, pollres=0;
        struct dahdi_pvt *i;
        struct dahdi_pvt *last = NULL;
+       struct dahdi_pvt *doomed;
        time_t thispass = 0, lastpass = 0;
        int found;
        char buf[1024];
@@ -8192,8 +8192,20 @@ static void *do_monitor(void *data)
                spoint = 0;
                lastpass = thispass;
                thispass = time(NULL);
-               i = iflist;
-               while (i) {
+               doomed = NULL;
+               for (i = iflist;; i = i->next) {
+                       if (doomed) {
+                               int res;
+                               res = dahdi_destroy_channel_bynum(doomed->channel);
+                               if (!res) {
+                                       ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
+                               }
+                               doomed = NULL;
+                       }
+                       if (!i) {
+                               break;
+                       }
+
                        if (thispass != lastpass) {
                                if (!found && ((i == last) || ((i == iflist) && !last))) {
                                        last = i;
@@ -8237,10 +8249,9 @@ static void *do_monitor(void *data)
                                                ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
                                                /* Don't hold iflock while handling init events */
                                                ast_mutex_unlock(&iflock);
-                                               handle_init_event(i, res);
+                                               doomed = handle_init_event(i, res);
                                                ast_mutex_lock(&iflock);        
                                        }
-                                       i = i->next;
                                        continue;
                                }                                       
                                pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
@@ -8250,12 +8261,10 @@ static void *do_monitor(void *data)
                                                if (!i->pri)
 #endif                                         
                                                        ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
-                                               i = i->next;
                                                continue;
                                        }
                                        if (!i->cidspill && !i->mwimonitor_fsk) {
                                                ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
-                                               i = i->next;
                                                continue;
                                        }
                                        res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
@@ -8309,18 +8318,16 @@ static void *do_monitor(void *data)
                                                if (!i->pri)
 #endif                                         
                                                        ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
-                                               i = i->next;
                                                continue;
                                        }
                                        res = dahdi_get_event(i->subs[SUB_REAL].dfd);
                                        ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
                                        /* Don't hold iflock while handling init events */
                                        ast_mutex_unlock(&iflock);
-                                       handle_init_event(i, res);
+                                       doomed = handle_init_event(i, res);
                                        ast_mutex_lock(&iflock);        
                                }
                        }
-                       i=i->next;
                }
                ast_mutex_unlock(&iflock);
        }