Browse code

- tcp fix: flags changed & membars() before derefs, more sanity checks and alias debugging

Andrei Pelinescu-Onciul authored on 28/12/2007 10:06:23
Showing 1 changed files
... ...
@@ -1383,6 +1383,7 @@ int tcpconn_add_alias(int id, int port, int proto)
1383 1383
 	struct tcp_connection* c;
1384 1384
 	int ret;
1385 1385
 	struct ip_addr zero_ip;
1386
+	int r;
1386 1387
 	
1387 1388
 	/* fix the port */
1388 1389
 	port=port?port:((proto==PROTO_TLS)?SIPS_PORT:SIP_PORT);
... ...
@@ -1415,8 +1416,16 @@ error:
1415 1415
 	TCPCONN_UNLOCK;
1416 1416
 	switch(ret){
1417 1417
 		case -2:
1418
-			LOG(L_ERR, "ERROR: tcpconn_add_alias: too many aliases"
1419
-					" for connection %p (%d)\n", c, c->id);
1418
+			LOG(L_ERR, "ERROR: tcpconn_add_alias: too many aliases (%d)"
1419
+					" for connection %p (id %d) %s:%d <- %d\n",
1420
+					c->aliases, c, c->id, ip_addr2a(&c->rcv.src_ip),
1421
+					c->rcv.src_port, port);
1422
+			for (r=0; r<c->aliases; r++){
1423
+				LOG(L_ERR, "ERROR: tcpconn_add_alias: alias %d: for %p (%d)"
1424
+						" %s:%d <-%d hash %x\n",  r, c, c->id, 
1425
+						 ip_addr2a(&c->rcv.src_ip), c->rcv.src_port, 
1426
+						c->con_aliases[r].port, c->con_aliases[r].hash);
1427
+			}
1420 1428
 			break;
1421 1429
 		case -3:
1422 1430
 			LOG(L_ERR, "ERROR: tcpconn_add_alias: possible port"
... ...
@@ -2075,10 +2084,11 @@ inline static int tcpconn_chld_put(struct tcp_connection* tcpconn)
2075 2075
 				"flags %04x\n", tcpconn, tcpconn->id,
2076 2076
 				tcpconn->s, tcpconn->flags);
2077 2077
 		/* sanity checks */
2078
+		membar_read_atomic_op(); /* make sure we see the current flags */
2078 2079
 		if (unlikely(!(tcpconn->flags & F_CONN_FD_CLOSED) || 
2079 2080
 					 !(tcpconn->flags & F_CONN_REMOVED) || 
2080 2081
 					(tcpconn->flags & 
2081
-					 		(F_CONN_HASHED| F_CONN_WRITE_W)) )){
2082
+					 	(F_CONN_HASHED|F_CONN_MAIN_TIMER| F_CONN_WRITE_W)) )){
2082 2083
 			LOG(L_CRIT, "BUG: tcpconn_chld_put: %p bad flags = %0x\n",
2083 2084
 					tcpconn, tcpconn->flags);
2084 2085
 			abort();
... ...
@@ -2131,25 +2141,41 @@ inline static void tcpconn_destroy(struct tcp_connection* tcpconn)
2131 2131
  */
2132 2132
 inline static int tcpconn_put_destroy(struct tcp_connection* tcpconn)
2133 2133
 {
2134
-	if (unlikely((tcpconn->flags & F_CONN_WRITE_W) ||
2135
-				!(tcpconn->flags & F_CONN_REMOVED))){
2134
+	if (unlikely((tcpconn->flags & 
2135
+						(F_CONN_WRITE_W|F_CONN_HASHED|F_CONN_MAIN_TIMER)) ||
2136
+				!(tcpconn->flags & F_CONN_REMOVED) )){
2136 2137
 		/* sanity check */
2137
-		LOG(L_CRIT, "BUG: tcpconn_put_destroy: %p flags = %0x\n",
2138
+		if (unlikely(tcpconn->flags & F_CONN_HASHED)){
2139
+			LOG(L_CRIT, "BUG: tcpconn_destroy: called with hashed and/or"
2140
+						"on timer connection (%p), flags = %0x\n",
2141
+						tcpconn, tcpconn->flags);
2142
+			/* try to continue */
2143
+			if (likely(tcpconn->flags & F_CONN_MAIN_TIMER))
2144
+				local_timer_del(&tcp_main_ltimer, &tcpconn->timer);
2145
+			TCPCONN_LOCK;
2146
+				_tcpconn_detach(tcpconn);
2147
+			TCPCONN_UNLOCK;
2148
+		}else{
2149
+			LOG(L_CRIT, "BUG: tcpconn_put_destroy: %p flags = %0x\n",
2138 2150
 					tcpconn, tcpconn->flags);
2151
+		}
2139 2152
 	}
2140
-	if (unlikely(atomic_dec_and_test(&tcpconn->refcnt))){
2141
-		tcpconn_destroy(tcpconn);
2153
+	tcpconn->state=S_CONN_BAD;
2154
+	/* in case it's still in a reader timer */
2155
+	tcpconn->timeout=get_ticks_raw();
2156
+	/* fast close: close fds now */
2157
+	if (likely(!(tcpconn->flags & F_CONN_FD_CLOSED))){
2158
+		tcpconn_close_main_fd(tcpconn);
2159
+		tcpconn->flags|=F_CONN_FD_CLOSED;
2160
+		(*tcp_connections_no)--;
2161
+	}
2162
+	/* all the flags / ops on the tcpconn must be done prior to decrementing
2163
+	 * the refcnt. and at least a membar_write_atomic_op() mem. barrier or
2164
+	 *  a mb_atomic_* op must * be used to make sure all the changed flags are
2165
+	 *  written into memory prior to the new refcnt value */
2166
+	if (unlikely(mb_atomic_dec_and_test(&tcpconn->refcnt))){
2167
+		_tcpconn_free(tcpconn);
2142 2168
 		return 1;
2143
-	}else{
2144
-		tcpconn->state=S_CONN_BAD;
2145
-		/* in case it's still in a reader timer */
2146
-		tcpconn->timeout=get_ticks_raw();
2147
-		/* fast close: close fds now */
2148
-		if (likely(!(tcpconn->flags & F_CONN_FD_CLOSED))){
2149
-			tcpconn_close_main_fd(tcpconn);
2150
-			tcpconn->flags|=F_CONN_FD_CLOSED;
2151
-			(*tcp_connections_no)--;
2152
-		}
2153 2169
 	}
2154 2170
 	return 0;
2155 2171
 }