[asterisk-commits] jpeeler: trunk r218430 - in /trunk: ./ channels/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Sep 14 17:38:29 CDT 2009


Author: jpeeler
Date: Mon Sep 14 17:38:25 2009
New Revision: 218430

URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=218430
Log:
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
........

Modified:
    trunk/   (props changed)
    trunk/channels/chan_dahdi.c
    trunk/channels/sig_analog.c
    trunk/channels/sig_analog.h

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Modified: trunk/channels/chan_dahdi.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/channels/chan_dahdi.c?view=diff&rev=218430&r1=218429&r2=218430
==============================================================================
--- trunk/channels/chan_dahdi.c (original)
+++ trunk/channels/chan_dahdi.c Mon Sep 14 17:38:25 2009
@@ -2411,6 +2411,9 @@
 	case DAHDI_EVENT_PULSE_START:
 		res = ANALOG_EVENT_PULSE_START;
 	break;
+	case DAHDI_EVENT_REMOVED:
+		res = ANALOG_EVENT_REMOVED;
+	break;
 	case DAHDI_EVENT_NEONMWI_ACTIVE:
 		res = ANALOG_EVENT_NEONMWI_ACTIVE;
 		break;
@@ -9916,8 +9919,7 @@
 	return RESULT_FAILURE;
 }
 
-/* returns < 0 = error, 0 event handled, >0 event handled and thread spawned */
-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;
 	int thread_spawned = 0;
@@ -10026,7 +10028,7 @@
 			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:
@@ -10083,7 +10085,7 @@
 		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:
@@ -10118,12 +10120,11 @@
 				"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);
@@ -10137,7 +10138,7 @@
 		}
 		break;
 	}
-	return thread_spawned;
+	return NULL;
 }
 
 static void *do_monitor(void *data)
@@ -10145,6 +10146,7 @@
 	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];
@@ -10243,7 +10245,20 @@
 		spoint = 0;
 		lastpass = thispass;
 		thispass = time(NULL);
-		for (i = iflist; i; i = i->next) {
+		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;
@@ -10283,9 +10298,9 @@
 						/* Don't hold iflock while handling init events */
 						ast_mutex_unlock(&iflock);
 						if (analog_lib_handles(i->sig, i->radio, i->oprmode))
-							analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
+							doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
 						else
-							handle_init_event(i, res);
+							doomed = handle_init_event(i, res);
 						ast_mutex_lock(&iflock);
 					}
 					continue;
@@ -10348,12 +10363,8 @@
 									struct ast_channel *chan;
 									ast_mutex_unlock(&iflock);
 									if (analog_lib_handles(i->sig, i->radio, i->oprmode)) {
-										res = analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
-										if (res) {
-											ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
-										} else {
-											i->dtmfcid_holdoff_state = 1;
-										}
+										analog_handle_init_event(i->sig_pvt, ANALOG_EVENT_DTMFCID);  
+										i->dtmfcid_holdoff_state = 1;
 									} else {
 										chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0, NULL);
 										if (!chan) {
@@ -10392,9 +10403,9 @@
 					ast_mutex_unlock(&iflock);
 					if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
 						if (analog_lib_handles(i->sig, i->radio, i->oprmode))
-							analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
+							doomed = (struct dahdi_pvt *) analog_handle_init_event(i->sig_pvt, dahdievent_to_analogevent(res));
 						else
-							handle_init_event(i, res);
+							doomed = handle_init_event(i, res);
 					}
 					ast_mutex_lock(&iflock);
 				}

Modified: trunk/channels/sig_analog.c
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/channels/sig_analog.c?view=diff&rev=218430&r1=218429&r2=218430
==============================================================================
--- trunk/channels/sig_analog.c (original)
+++ trunk/channels/sig_analog.c Mon Sep 14 17:38:25 2009
@@ -255,6 +255,9 @@
 		break;
 	case ANALOG_EVENT_PULSE_START:
 		res = "ANALOG_EVENT_PULSE_START";
+		break;
+	case ANALOG_EVENT_REMOVED:
+		res = "ANALOG_EVENT_REMOVED";
 		break;
 	case ANALOG_EVENT_NEONMWI_ACTIVE:
 		res = "ANALOG_EVENT_NEONMWI_ACTIVE";
@@ -3169,18 +3172,15 @@
 	return f;
 }
 
-int analog_handle_init_event(struct analog_pvt *i, int event)
+void *analog_handle_init_event(struct analog_pvt *i, int event)
 {
 	int res;
 	pthread_t threadid;
-	pthread_attr_t attr;
 	struct ast_channel *chan;
 
 	ast_debug(1, "channel (%d) - signaling (%d) - event (%s)\n",
 				i->channel, i->sig, analog_event2str(event));
 
-	pthread_attr_init(&attr);
-	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 	/* Handle an event on a given channel for the monitor thread. */
 	switch (event) {
 	case ANALOG_EVENT_WINKFLASH:
@@ -3223,7 +3223,8 @@
 					}
 					if (res < 0)
 						ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
-					if (ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) {
+
+					if (ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) {
 						ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
 						res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
 						if (res < 0) {
@@ -3262,7 +3263,7 @@
 				chan = analog_new_ast_channel(i, AST_STATE_RING, 0, ANALOG_SUB_REAL, NULL);
 			}
 			i->ss_astchan = chan;
-			if (chan && ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) {
+			if (chan && ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) {
 				ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
 				res = analog_play_tone(i, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
 				if (res < 0) {
@@ -3279,7 +3280,7 @@
 			if (res < 0) {
 				ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
 			}
-			return -1;
+			return NULL;
 		}
 		break;
 	case ANALOG_EVENT_NOALARM:
@@ -3339,7 +3340,7 @@
 		default:
 			ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", analog_sigtype_to_str(i->sig), i->channel);
 			res = analog_play_tone(i, ANALOG_SUB_REAL, -1);
-			return -1;
+			return NULL;
 		}
 		break;
 	case ANALOG_EVENT_POLARITY:
@@ -3362,7 +3363,7 @@
 					    i->channel);
 				chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL);
 				i->ss_astchan = chan;
-				if (chan && ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) {
+				if (chan && ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) {
 					ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
 				}
 			}
@@ -3383,7 +3384,7 @@
 								i->channel);
 					chan = analog_new_ast_channel(i, AST_STATE_PRERING, 0, ANALOG_SUB_REAL, NULL);
 					i->ss_astchan = chan;
-					if (chan && ast_pthread_create(&threadid, &attr, __analog_ss_thread, i)) {
+					if (chan && ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, i)) {
 						ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
 					}
 				}
@@ -3394,6 +3395,12 @@
 								"interface %d\n", i->channel);
 		}
 		break;
+	case ANALOG_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);
+        return i->chan_pvt;
+        break;
 	case ANALOG_EVENT_NEONMWI_ACTIVE:
 		analog_handle_notify_message(NULL, i, -1, ANALOG_EVENT_NEONMWI_ACTIVE);
 		break;
@@ -3401,8 +3408,7 @@
 		analog_handle_notify_message(NULL, i, -1, ANALOG_EVENT_NEONMWI_INACTIVE);
 		break;
 	}
-	pthread_attr_destroy(&attr);
-	return 0;
+	return NULL;
 }
 
 

Modified: trunk/channels/sig_analog.h
URL: http://svn.asterisk.org/svn-view/asterisk/trunk/channels/sig_analog.h?view=diff&rev=218430&r1=218429&r2=218430
==============================================================================
--- trunk/channels/sig_analog.h (original)
+++ trunk/channels/sig_analog.h Mon Sep 14 17:38:25 2009
@@ -78,6 +78,7 @@
 	ANALOG_EVENT_RINGBEGIN,
 	ANALOG_EVENT_PULSE_START,
 	ANALOG_EVENT_ERROR,
+	ANALOG_EVENT_REMOVED,
 	ANALOG_EVENT_NEONMWI_ACTIVE,
 	ANALOG_EVENT_NEONMWI_INACTIVE,
 	ANALOG_EVENT_DTMFCID,
@@ -328,7 +329,7 @@
 
 int analog_available(struct analog_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched);
 
-int analog_handle_init_event(struct analog_pvt *i, int event);
+void *analog_handle_init_event(struct analog_pvt *i, int event);
 
 int analog_config_complete(struct analog_pvt *p);
 




More information about the asterisk-commits mailing list