Browse Source

- deadlock when t_relay-ing a message from the failure_route fixed
(e2e_cancel uses now t_reply_unsafe when called from the failure_route)

Andrei Pelinescu-Onciul 19 years ago
parent
commit
73194f939d
4 changed files with 44 additions and 13 deletions
  1. 1 1
      Makefile.defs
  2. 4 0
      modules/tm/t_funcs.c
  3. 36 9
      modules/tm/t_fwd.c
  4. 3 3
      modules/tm/tm_load.h

+ 1 - 1
Makefile.defs

@@ -59,7 +59,7 @@ MAIN_NAME=ser
 VERSION = 0
 PATCHLEVEL = 9
 SUBLEVEL = 7
-EXTRAVERSION = -pre4
+EXTRAVERSION = -pre5
 
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")

+ 4 - 0
modules/tm/t_funcs.c

@@ -178,6 +178,8 @@ void put_on_wait(  struct cell  *Trans  )
 
 
 
+/* WARNING: doesn't work from failure route (deadlock, uses t_reply =>
+ *  tries to get the reply lock again) */
 static int kill_transaction( struct cell *trans )
 {
 	char err_buffer[128];
@@ -205,6 +207,8 @@ static int kill_transaction( struct cell *trans )
 
 
 
+/* WARNING: doesn't work from failure route (deadlock, uses t_reply => tries
+ *  to get the reply lock again */
 int t_relay_to( struct sip_msg  *p_msg , struct proxy_l *proxy, int proto,
 				int replicate)
 {

+ 36 - 9
modules/tm/t_fwd.c

@@ -42,6 +42,8 @@
  *  2003-12-04  global TM callbacks switched to per transaction callbacks
  *              (bogdan)
  *  2004-02-13: t->is_invite and t->local replaced with flags (bogdan)
+ *  2006-08-28  e2e_cancel uses t_reply_unsafe when called from the 
+ *               failure_route and replying to a cancel (andrei)
  */
 
 #include "defs.h"
@@ -364,19 +366,40 @@ void e2e_cancel( struct sip_msg *cancel_msg,
 	*/
 	if (lowest_error<0) {
 		LOG(L_ERR, "ERROR: cancel error\n");
-		t_reply( t_cancel, cancel_msg, 500, "cancel error");
-	/* if there are pending branches, let upstream know we
-	   are working on it
-	*/
+		/* if called from failure_route, make sure that the unsafe version
+		 * is called (we are already hold the reply mutex for the cancel
+		 * transaction).
+		 */
+		if (rmode==MODE_ONFAILURE)
+			t_reply_unsafe( t_cancel, cancel_msg, 500, "cancel error");
+		else
+			t_reply( t_cancel, cancel_msg, 500, "cancel error");
 	} else if (cancel_bm) {
+		/* if there are pending branches, let upstream know we
+		   are working on it
+		*/
 		DBG("DEBUG: e2e_cancel: e2e cancel proceeding\n");
-		t_reply( t_cancel, cancel_msg, 200, CANCELING );
-	/* if the transaction exists, but there is no more pending
-	   branch, tell upstream we're done
-	*/
+		/* if called from failure_route, make sure that the unsafe version
+		 * is called (we are already hold the reply mutex for the cancel
+		 * transaction).
+		 */
+		if (rmode==MODE_ONFAILURE)
+			t_reply_unsafe( t_cancel, cancel_msg, 200, CANCELING );
+		else
+			t_reply( t_cancel, cancel_msg, 200, CANCELING );
 	} else {
+		/* if the transaction exists, but there is no more pending
+		   branch, tell upstream we're done
+		*/
 		DBG("DEBUG: e2e_cancel: e2e cancel -- no more pending branches\n");
-		t_reply( t_cancel, cancel_msg, 200, CANCEL_DONE );
+		/* if called from failure_route, make sure that the unsafe version
+		 * is called (we are already hold the reply mutex for the cancel
+		 * transaction).
+		 */
+		if (rmode==MODE_ONFAILURE)
+			t_reply_unsafe( t_cancel, cancel_msg, 200, CANCEL_DONE );
+		else
+			t_reply( t_cancel, cancel_msg, 200, CANCEL_DONE );
 	}
 
 #ifdef LOCAL_487
@@ -513,6 +536,10 @@ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg ,
 	return 1;
 }	
 
+
+
+/* WARNING: doesn't work from failure route (deadlock, uses t_relay_to which
+ *  is failure route unsafe) */
 int t_replicate(struct sip_msg *p_msg,  struct proxy_l *proxy, int proto )
 {
 	/* this is a quite horrible hack -- we just take the message

+ 3 - 3
modules/tm/tm_load.h

@@ -75,9 +75,9 @@
 
 struct tm_binds {
 	register_tmcb_f  register_tmcb;
-	cmd_function     t_relay_to_udp;
-	cmd_function     t_relay_to_tcp;
-	cmd_function     t_relay;
+	cmd_function     t_relay_to_udp; /* WARNING: failure_route unsafe */
+	cmd_function     t_relay_to_tcp; /* WARNING: failure_route unsafe */ 
+	cmd_function     t_relay;        /* WARNING: failure_route unsafe */
 	tnewtran_f       t_newtran;
 	treply_f         t_reply;
 	treply_wb_f      t_reply_with_body;