Просмотр исходного кода

- cancel relayed from failure route deadlock fix ported from stable
(e2e_cancel uses now t_reply_unsafe when called from the failure_route)

Andrei Pelinescu-Onciul 19 лет назад
Родитель
Сommit
aaed15a3a8
4 измененных файлов с 44 добавлено и 13 удалено
  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

@@ -66,7 +66,7 @@ MAIN_NAME=ser
 VERSION = 0
 PATCHLEVEL = 10
 SUBLEVEL =   99
-EXTRAVERSION = -dev43-dns_cache
+EXTRAVERSION = -dev44-dns_cache
 
 SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
 			$(SUBLEVEL) )

+ 4 - 0
modules/tm/t_funcs.c

@@ -169,6 +169,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];
@@ -196,6 +198,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

@@ -54,6 +54,8 @@
  *              t_forward_non_ack won't start retransmission on send errors
  *               anymore (WARNING: callers should release/kill the transaction
  *               if error is returned) (andrei)
+ *  2006-09-15  e2e_cancel uses t_reply_unsafe when called from the 
+ *               failure_route and replying to a cancel (andrei)
  */
 
 #include "defs.h"
@@ -517,19 +519,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_cancel==get_t()))
+			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_cancel==get_t()))
+			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_cancel==get_t()))
+			t_reply_unsafe( t_cancel, cancel_msg, 200, CANCEL_DONE );
+		else
+			t_reply( t_cancel, cancel_msg, 200, CANCEL_DONE );
 	}
 }
 
@@ -798,6 +821,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

@@ -76,9 +76,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;