diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 0487d523857cadc8d68d48ea17b1a574df817175..6b63ed3816c58318942a66dbe762824b24b27958 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -15536,8 +15536,9 @@ static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli
 				struct sig_pri_chan *chan = tmp->sig_pvt;
 
 				ast_cli(a->fd, "PRI Flags: ");
-				if (chan->resetting)
-					ast_cli(a->fd, "Resetting ");
+				if (chan->resetting != SIG_PRI_RESET_IDLE) {
+					ast_cli(a->fd, "Resetting=%d ", chan->resetting);
+				}
 				if (chan->call)
 					ast_cli(a->fd, "Call ");
 				if (chan->allocated) {
diff --git a/channels/sig_pri.c b/channels/sig_pri.c
index 47724a8e94e9043d2223dd3b7b8beee320f4b724..28bb6712f80a848a4c20475123a7f74e0ad59493 100644
--- a/channels/sig_pri.c
+++ b/channels/sig_pri.c
@@ -196,11 +196,11 @@ void sig_pri_set_alarm(struct sig_pri_chan *p, int in_alarm)
 	}
 
 	/*
-	 * Clear the channel restart flag when the channel alarm changes
-	 * to prevent the flag from getting stuck when the link goes
-	 * down.
+	 * Clear the channel restart state when the channel alarm
+	 * changes to prevent the state from getting stuck when the link
+	 * goes down.
 	 */
-	p->resetting = 0;
+	p->resetting = SIG_PRI_RESET_IDLE;
 
 	p->inalarm = in_alarm;
 	if (p->calls->set_alarm) {
@@ -1159,7 +1159,8 @@ static void pri_find_dchan(struct sig_pri_span *pri)
  */
 static int sig_pri_is_chan_in_use(struct sig_pri_chan *pvt)
 {
-	return pvt->owner || pvt->call || pvt->allocated || pvt->resetting || pvt->inalarm;
+	return pvt->owner || pvt->call || pvt->allocated || pvt->inalarm
+		|| pvt->resetting != SIG_PRI_RESET_IDLE;
 }
 
 /*!
@@ -1714,7 +1715,7 @@ static void pri_check_restart(struct sig_pri_span *pri)
 	}
 	if (pri->resetpos < pri->numchans) {
 		/* Mark the channel as resetting and restart it */
-		pri->pvts[pri->resetpos]->resetting = 1;
+		pri->pvts[pri->resetpos]->resetting = SIG_PRI_RESET_ACTIVE;
 		pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
 	} else {
 		pri->resetting = 0;
@@ -5951,13 +5952,40 @@ static void *pri_dchannel(void *vpri)
 							"Span %d: SETUP on unconfigured channel %d/%d\n",
 							pri->span, PRI_SPAN(e->ring.channel),
 							PRI_CHANNEL(e->ring.channel));
-					} else if (!sig_pri_is_chan_available(pri->pvts[chanpos])) {
-						/* This is where we handle initial glare */
-						ast_debug(1,
-							"Span %d: SETUP requested unavailable channel %d/%d.  Attempting to renegotiate.\n",
-							pri->span, PRI_SPAN(e->ring.channel),
-							PRI_CHANNEL(e->ring.channel));
-						chanpos = -1;
+					} else {
+						switch (pri->pvts[chanpos]->resetting) {
+						case SIG_PRI_RESET_IDLE:
+							break;
+						case SIG_PRI_RESET_ACTIVE:
+							/*
+							 * The peer may have lost the expected ack or not received the
+							 * RESTART yet.
+							 */
+							pri->pvts[chanpos]->resetting = SIG_PRI_RESET_NO_ACK;
+							break;
+						case SIG_PRI_RESET_NO_ACK:
+							/* The peer likely is not going to ack the RESTART. */
+							ast_debug(1,
+								"Span %d: Second SETUP while waiting for RESTART ACKNOWLEDGE on channel %d/%d\n",
+								pri->span, PRI_SPAN(e->ring.channel),
+								PRI_CHANNEL(e->ring.channel));
+
+							/* Assume we got the ack. */
+							pri->pvts[chanpos]->resetting = SIG_PRI_RESET_IDLE;
+							if (pri->resetting) {
+								/* Go on to the next idle channel to RESTART. */
+								pri_check_restart(pri);
+							}
+							break;
+						}
+						if (!sig_pri_is_chan_available(pri->pvts[chanpos])) {
+							/* This is where we handle initial glare */
+							ast_debug(1,
+								"Span %d: SETUP requested unavailable channel %d/%d.  Attempting to renegotiate.\n",
+								pri->span, PRI_SPAN(e->ring.channel),
+								PRI_CHANNEL(e->ring.channel));
+							chanpos = -1;
+						}
 					}
 #if defined(ALWAYS_PICK_CHANNEL)
 					if (e->ring.flexible) {
@@ -6778,12 +6806,12 @@ static void *pri_dchannel(void *vpri)
 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
 				if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
 					&& pri->sig != SIG_BRI_PTMP && !pri->resetting
-					&& !pri->pvts[chanpos]->resetting) {
+					&& pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) {
 					ast_verb(3,
 						"Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
 						pri->span, pri->pvts[chanpos]->logicalspan,
 						pri->pvts[chanpos]->prioffset);
-					pri->pvts[chanpos]->resetting = 1;
+					pri->pvts[chanpos]->resetting = SIG_PRI_RESET_ACTIVE;
 					pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
 				}
 #endif	/* defined(FORCE_RESTART_UNAVAIL_CHANS) */
@@ -6926,12 +6954,12 @@ static void *pri_dchannel(void *vpri)
 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
 				if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
 					&& pri->sig != SIG_BRI_PTMP && !pri->resetting
-					&& !pri->pvts[chanpos]->resetting) {
+					&& pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) {
 					ast_verb(3,
 						"Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
 						pri->span, pri->pvts[chanpos]->logicalspan,
 						pri->pvts[chanpos]->prioffset);
-					pri->pvts[chanpos]->resetting = 1;
+					pri->pvts[chanpos]->resetting = SIG_PRI_RESET_ACTIVE;
 					pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
 				}
 #endif	/* defined(FORCE_RESTART_UNAVAIL_CHANS) */
@@ -6995,7 +7023,8 @@ static void *pri_dchannel(void *vpri)
 					   channel number, so we have to figure it out...  This must be why
 					   everybody resets exactly a channel at a time. */
 					for (x = 0; x < pri->numchans; x++) {
-						if (pri->pvts[x] && pri->pvts[x]->resetting) {
+						if (pri->pvts[x]
+							&& pri->pvts[x]->resetting != SIG_PRI_RESET_IDLE) {
 							chanpos = x;
 							sig_pri_lock_private(pri->pvts[chanpos]);
 							ast_debug(1,
@@ -7009,7 +7038,7 @@ static void *pri_dchannel(void *vpri)
 									pri->pvts[chanpos]->prioffset);
 								ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
 							}
-							pri->pvts[chanpos]->resetting = 0;
+							pri->pvts[chanpos]->resetting = SIG_PRI_RESET_IDLE;
 							ast_verb(3,
 								"Span %d: Channel %d/%d successfully restarted\n",
 								pri->span, pri->pvts[chanpos]->logicalspan,
@@ -7028,6 +7057,15 @@ static void *pri_dchannel(void *vpri)
 					}
 				} else {
 					sig_pri_lock_private(pri->pvts[chanpos]);
+					if (pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) {
+						/* The channel is not in the resetting state. */
+						ast_debug(1,
+							"Span %d: Unexpected or late restart ack on channel %d/%d (Ignoring)\n",
+							pri->span, pri->pvts[chanpos]->logicalspan,
+							pri->pvts[chanpos]->prioffset);
+						sig_pri_unlock_private(pri->pvts[chanpos]);
+						break;
+					}
 					if (pri->pvts[chanpos]->owner) {
 						ast_log(LOG_WARNING,
 							"Span %d: Got restart ack on channel %d/%d with owner\n",
@@ -7035,7 +7073,7 @@ static void *pri_dchannel(void *vpri)
 							pri->pvts[chanpos]->prioffset);
 						ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
 					}
-					pri->pvts[chanpos]->resetting = 0;
+					pri->pvts[chanpos]->resetting = SIG_PRI_RESET_IDLE;
 					ast_verb(3,
 						"Span %d: Channel %d/%d successfully restarted\n",
 						pri->span, pri->pvts[chanpos]->logicalspan,
diff --git a/channels/sig_pri.h b/channels/sig_pri.h
index 7a48d824af6ae1b276242d2f925a3fac3e8fd647..6c1ca2aa38605c3bf29dc19aaee97d5aa9ce6249 100644
--- a/channels/sig_pri.h
+++ b/channels/sig_pri.h
@@ -150,6 +150,27 @@ enum sig_pri_call_level {
 	SIG_PRI_CALL_LEVEL_CONNECT,
 };
 
+enum sig_pri_reset_state {
+	/*! \brief The channel is not being RESTARTed. */
+	SIG_PRI_RESET_IDLE,
+	/*!
+	 * \brief The channel is being RESTARTed.
+	 * \note Waiting for a RESTART ACKNOWLEDGE from the peer.
+	 */
+	SIG_PRI_RESET_ACTIVE,
+	/*!
+	 * \brief Peer may not be sending the expected RESTART ACKNOWLEDGE.
+	 *
+	 * \details We have already received a SETUP on this channel.
+	 * If another SETUP comes in on this channel then the peer
+	 * considers this channel useable.  Assume that the peer is
+	 * never going to give us a RESTART ACKNOWLEDGE and assume that
+	 * we have received one.  This is not according to Q.931, but
+	 * some peers occasionally fail to send a RESTART ACKNOWLEDGE.
+	 */
+	SIG_PRI_RESET_NO_ACK,
+};
+
 struct sig_pri_span;
 
 struct sig_pri_callback {
@@ -299,7 +320,6 @@ struct sig_pri_chan {
 	unsigned int alreadyhungup:1;	/*!< TRUE if the call has already gone/hungup */
 	unsigned int isidlecall:1;		/*!< TRUE if this is an idle call */
 	unsigned int progress:1;		/*!< TRUE if the call has seen inband-information progress through the network */
-	unsigned int resetting:1;		/*!< TRUE if this channel is being reset/restarted */
 
 	/*!
 	 * \brief TRUE when this channel is allocated.
@@ -328,6 +348,8 @@ struct sig_pri_chan {
 
 	/*! Call establishment life cycle level for simple comparisons. */
 	enum sig_pri_call_level call_level;
+	/*! \brief Channel reset/restart state. */
+	enum sig_pri_reset_state resetting;
 	int prioffset;					/*!< channel number in span */
 	int logicalspan;				/*!< logical span number within trunk group */
 	int mastertrunkgroup;			/*!< what trunk group is our master */