[asterisk-commits] rmudgett: branch 10 r336978 - in /branches/10: ./ channels/sig_ss7.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Sep 20 13:14:42 CDT 2011


Author: rmudgett
Date: Tue Sep 20 13:14:40 2011
New Revision: 336978

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=336978
Log:
Merged revisions 336977 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.8

........
  r336977 | rmudgett | 2011-09-20 13:12:17 -0500 (Tue, 20 Sep 2011) | 21 lines
  
  Fix deadlock from not releasing SS7 linkset lock.
  
  sig_ss7_hangup() failed to release the SS7 linkset lock if the call had
  the alreadyhungup flag set.
  
  * Made unlock the SS7 linkset lock in sig_ss7_hangup() if the
  alreadyhungup flag is set.
  
  * Made ss7_start_call() not hold any locks while creating the channel for
  an incoming call to prevent deadlock.
  
  * Made ss7_grab() a void function, since it could never fail, to simplify
  calling code.
  
  * Made obtain the channel lock to do softhangup in some places.
  
  Patches:
        jira_ast_668_v1.8.patch (license #5621) patch uploaded by rmudgett
  
  JIRA AST-668
........

Modified:
    branches/10/   (props changed)
    branches/10/channels/sig_ss7.c

Propchange: branches/10/
------------------------------------------------------------------------------
Binary property 'branch-1.8-merged' - no diff available.

Modified: branches/10/channels/sig_ss7.c
URL: http://svnview.digium.com/svn/asterisk/branches/10/channels/sig_ss7.c?view=diff&rev=336978&r1=336977&r2=336978
==============================================================================
--- branches/10/channels/sig_ss7.c (original)
+++ branches/10/channels/sig_ss7.c Tue Sep 20 13:14:40 2011
@@ -454,19 +454,26 @@
 	}
 
 	/*
-	 * Release the SS7 lock while we create the channel
-	 * so other threads can send messages.
+	 * Release the SS7 lock while we create the channel so other
+	 * threads can send messages.  We must also release the private
+	 * lock to prevent deadlock while creating the channel.
 	 */
 	ast_mutex_unlock(&linkset->lock);
+	sig_ss7_unlock_private(p);
 	c = sig_ss7_new_ast_channel(p, AST_STATE_RING, law, 0, p->exten, NULL);
 	if (!c) {
 		ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
 		ast_mutex_lock(&linkset->lock);
+		sig_ss7_lock_private(p);
 		isup_rel(linkset->ss7, p->ss7call, -1);
 		p->call_level = SIG_SS7_CALL_LEVEL_IDLE;
 		p->alreadyhungup = 1;
 		return;
 	}
+
+	/* Hold the channel and private lock while we setup the channel. */
+	ast_channel_lock(c);
+	sig_ss7_lock_private(p);
 
 	sig_ss7_set_echocanceller(p, 1);
 
@@ -549,13 +556,19 @@
 		p->generic_name[0] = 0;
 	}
 
+	sig_ss7_unlock_private(p);
+	ast_channel_unlock(c);
+
 	if (ast_pbx_start(c)) {
 		ast_log(LOG_WARNING, "Unable to start PBX on %s (CIC %d)\n", c->name, p->cic);
 		ast_hangup(c);
 	} else {
 		ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
 	}
+
+	/* Must return with linkset and private lock. */
 	ast_mutex_lock(&linkset->lock);
+	sig_ss7_lock_private(p);
 }
 
 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct sig_ss7_linkset *ss7, const char *number, const unsigned nai)
@@ -739,9 +752,12 @@
 				sig_ss7_set_remotelyblocked(p, 0);
 				dpc = p->dpc;
 				isup_set_call_dpc(e->rsc.call, dpc);
+				sig_ss7_lock_owner(linkset, chanpos);
 				p->ss7call = NULL;
-				if (p->owner)
-					p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+				if (p->owner) {
+					ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
+					ast_channel_unlock(p->owner);
+				}
 				sig_ss7_unlock_private(p);
 				isup_rlc(ss7, e->rsc.call);
 				break;
@@ -912,9 +928,11 @@
 				}
 				p = linkset->pvts[chanpos];
 				sig_ss7_lock_private(p);
+				sig_ss7_lock_owner(linkset, chanpos);
 				if (p->owner) {
 					p->owner->hangupcause = e->rel.cause;
-					p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+					ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
+					ast_channel_unlock(p->owner);
 				} else {
 					ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
 				}
@@ -1088,8 +1106,8 @@
 					else
 						ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL.  Ignoring.\n");
 					sig_ss7_unlock_private(p);
-					}
-					break;
+				}
+				break;
 			case ISUP_EVENT_FAA:
 				chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
 				if (chanpos < 0) {
@@ -1122,7 +1140,7 @@
 	ast_mutex_unlock(&ss7->lock);
 }
 
-static inline int ss7_grab(struct sig_ss7_chan *pvt, struct sig_ss7_linkset *ss7)
+static void ss7_grab(struct sig_ss7_chan *pvt, struct sig_ss7_linkset *ss7)
 {
 	int res;
 	/* Grab the lock first */
@@ -1135,7 +1153,6 @@
 	/* Then break the poll */
 	if (ss7->master != AST_PTHREADT_NULL)
 		pthread_kill(ss7->master, SIGURG);
-	return 0;
 }
 
 /*!
@@ -1302,10 +1319,7 @@
 		l = NULL;
 	}
 
-	if (ss7_grab(p, p->ss7)) {
-		ast_log(LOG_WARNING, "Failed to grab SS7!\n");
-		return -1;
-	}
+	ss7_grab(p, p->ss7);
 
 	p->ss7call = isup_new_call(p->ss7->ss7);
 	if (!p->ss7call) {
@@ -1428,24 +1442,22 @@
 	p->exten[0] = '\0';
 	/* Perform low level hangup if no owner left */
 	if (p->ss7call) {
-		if (!ss7_grab(p, p->ss7)) {
-			if (!p->alreadyhungup) {
-				const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
-				int icause = ast->hangupcause ? ast->hangupcause : -1;
-
-				if (cause) {
-					if (atoi(cause))
-						icause = atoi(cause);
-				}
-				isup_rel(p->ss7->ss7, p->ss7call, icause);
-				ss7_rel(p->ss7);
-				p->alreadyhungup = 1;
-			} else
-				ast_log(LOG_WARNING, "Trying to hangup twice!\n");
+		ss7_grab(p, p->ss7);
+		if (!p->alreadyhungup) {
+			const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
+			int icause = ast->hangupcause ? ast->hangupcause : -1;
+
+			if (cause) {
+				if (atoi(cause)) {
+					icause = atoi(cause);
+				}
+			}
+			isup_rel(p->ss7->ss7, p->ss7call, icause);
+			p->alreadyhungup = 1;
 		} else {
-			ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
-			res = -1;
-		}
+			ast_log(LOG_WARNING, "Trying to hangup twice!\n");
+		}
+		ss7_rel(p->ss7);
 	}
 
 	return res;
@@ -1465,16 +1477,12 @@
 {
 	int res;
 
-	if (!ss7_grab(p, p->ss7)) {
-		if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) {
-			p->call_level = SIG_SS7_CALL_LEVEL_CONNECT;
-		}
-		res = isup_anm(p->ss7->ss7, p->ss7call);
-		ss7_rel(p->ss7);
-	} else {
-		ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->ss7->span);
-		res = -1;
-	}
+	ss7_grab(p, p->ss7);
+	if (p->call_level < SIG_SS7_CALL_LEVEL_CONNECT) {
+		p->call_level = SIG_SS7_CALL_LEVEL_CONNECT;
+	}
+	res = isup_anm(p->ss7->ss7, p->ss7call);
+	ss7_rel(p->ss7);
 	return res;
 }
 




More information about the asterisk-commits mailing list