Browse code

b/f: fixes possible deadlock when messages are sent from handle_sip_reply().

Original patch by Stefan, slightly extended.

Raphael Coeffic authored on 26/01/2012 11:28:49
Showing 2 changed files
... ...
@@ -154,13 +154,15 @@ void trans_timer_cb(timer* t, unsigned int bucket_id, sip_trans* tr)
154 154
 	if(bucket->exist(tr)){
155 155
 	    DBG("Transaction timer expired: type=%c, trans=%p, eta=%i, t=%i\n",
156 156
 		timer_name(t->type),tr,t->expires,wheeltimer::instance()->wall_clock);
157
+
158
+	    // timer_expired unlocks the bucket
157 159
 	    trans_layer::instance()->timer_expired(t,bucket,tr);
158 160
 	}
159 161
 	else {
160 162
 	    WARN("Ignoring expired timer (%p): transaction"
161 163
 		 " %p does not exist anymore\n",t,tr);
164
+	    bucket->unlock();
162 165
 	}
163
-	bucket->unlock();
164 166
     }
165 167
     else {
166 168
 	ERROR("Invalid bucket id\n");
... ...
@@ -747,9 +747,10 @@ void _trans_layer::timeout(trans_bucket* bucket, sip_trans* t)
747 747
     msg.cseq = req->cseq;
748 748
     msg.callid = req->callid;
749 749
 
750
-    ua->handle_sip_reply(&msg);
751
-
752 750
     bucket->remove(t);
751
+    bucket->unlock();
752
+
753
+    ua->handle_sip_reply(&msg);
753 754
 }
754 755
 
755 756
 int _trans_layer::send_request(sip_msg* msg, trans_ticket* tt,
... ...
@@ -1204,10 +1205,18 @@ void _trans_layer::received_msg(sip_msg* msg)
1204 1205
 	    // Reply matched UAC transaction
1205 1206
 	    
1206 1207
 	    DBG("Reply matched an existing transaction\n");
1207
-	    if(update_uac_reply(bucket,t,msg) < 0){
1208
+	    int res = update_uac_reply(bucket,t,msg);
1209
+	    if(res < 0){
1208 1210
 		ERROR("update_uac_trans() failed, so what happens now???\n");
1209 1211
 		break;
1210 1212
 	    }
1213
+	    if (res) {
1214
+		bucket->unlock();
1215
+		ua->handle_sip_reply(msg);
1216
+		DROP_MSG;
1217
+		//return; - part of DROP_MSG
1218
+	    }
1219
+
1211 1220
 	    // do not touch the transaction anymore:
1212 1221
 	    // it could have been deleted !!!
1213 1222
 	}
... ...
@@ -1406,8 +1415,7 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg*
1406 1415
     }
1407 1416
 
1408 1417
  pass_reply:
1409
-    assert(ua);
1410
-    ua->handle_sip_reply(msg);
1418
+    return 1;
1411 1419
  end:
1412 1420
     return 0;
1413 1421
 }
... ...
@@ -1648,7 +1656,9 @@ void _trans_layer::timer_expired(timer* t, trans_bucket* bucket, sip_trans* tr)
1648 1656
 	tr->clear_timer(STIMER_B);
1649 1657
 	if(tr->state == TS_CALLING) {
1650 1658
 	    DBG("Transaction timeout!\n");
1659
+	    // unlocks the bucket
1651 1660
 	    timeout(bucket,tr);
1661
+	    return;
1652 1662
 	}
1653 1663
 	else {
1654 1664
 	    DBG("Transaction timeout timer hit while state=0x%x",tr->state);
... ...
@@ -1664,8 +1674,9 @@ void _trans_layer::timer_expired(timer* t, trans_bucket* bucket, sip_trans* tr)
1664 1674
 	case TS_TRYING:
1665 1675
 	case TS_PROCEEDING:
1666 1676
 	    DBG("Transaction timeout!\n");
1677
+	    // unlocks the bucket
1667 1678
 	    timeout(bucket,tr);
1668
-	    break;
1679
+	    return;
1669 1680
 	}
1670 1681
 	break;
1671 1682
 
... ...
@@ -1751,7 +1762,7 @@ void _trans_layer::timer_expired(timer* t, trans_bucket* bucket, sip_trans* tr)
1751 1762
 	    // get the next ip
1752 1763
 	    if(tr->msg->h_dns.next_ip(&sa) < 0){
1753 1764
 		tr->clear_timer(STIMER_M);
1754
-		return;
1765
+		break;
1755 1766
 	    }
1756 1767
 
1757 1768
 	    //If a SRV record is involved, the port number
... ...
@@ -1786,6 +1797,8 @@ void _trans_layer::timer_expired(timer* t, trans_bucket* bucket, sip_trans* tr)
1786 1797
 	ERROR("Invalid timer type %i\n",t->type);
1787 1798
 	break;
1788 1799
     }
1800
+
1801
+    bucket->unlock();
1789 1802
 }
1790 1803
 
1791 1804
 /**