Alan DeKok [[email protected]] wrote:
> Sent: Friday, March 09, 2012 3:25 AM
> Brian Julin wrote:
> > This keeps the server listening, but there are some lingering issues:
>
>  Well, fixes are welcome.
>
>  I don't have time to look into this for a few weeks at least.

request_proxy_anew was assuming its argument would be installed in the
proxy_list, which wasn't the case, so it was removing it twice causing 
.num_outgoing counters to roll over.  Then, request_proxy was not expecting
the case where the argument was already in the proxy_list (put there by
request_proxy_anew) and was failing when attempting to add it a second
time.  The latter makes me wonder why or if request_proxy_anew works at all.

The attached patch seems to do the trick.  Some caveats:

This bypasses (for certain situations) the attempts to make sure that
a duplicate packet does not reuse the proxy_list ID of its predecessor.
Not knowing the reasoning behind that, I don't know if that's important
or not.

request_proxy has a "retransmit" flag as a parameter, which might be the
better test to avoid inserting the entry twice, or might not be.

Off topic, JOOC, while reading through the source I was left wondering what
prevents proxy_wait_for_reply from entering master-only functions from a
non-master thread when it falls through the DUP case into the TIMER case.

diff --git a/src/main/process.c b/src/main/process.c
index 4b5f084..f3b0c3f 100644
--- a/src/main/process.c
+++ b/src/main/process.c
@@ -1596,7 +1596,7 @@ static void remove_from_proxy_hash_nl(REQUEST *request)
 	request->proxy_listener = NULL;
 
 	/*
-	 *	Got from YES in hash, to NO, not in hash while we hold
+	 *	Go from YES in hash, to NO, not in hash while we hold
 	 *	the mutex.  This guarantees that when another thread
 	 *	grabs the mutex, the "not in hash" flag is correct.
 	 */
@@ -2264,7 +2264,7 @@ static int request_proxy(REQUEST *request, int retransmit)
 	/*
 	 *	We're actually sending a proxied packet.  Do that now.
 	 */
-	if (!insert_into_proxy_hash(request)) {
+	if (!request->in_proxy_hash && !insert_into_proxy_hash(request)) {
 		radlog_request(L_PROXY, 0, request, "Failed to insert initial packet into the proxy list.");
 		return -1;
 	}
@@ -2298,9 +2298,13 @@ static int request_proxy_anew(REQUEST *request)
 	/*
 	 *	Keep a copy of the old Id so that the
 	 *	re-transmitted request doesn't re-use the old
-	 *	Id.
+	 *	Id.  Note that in certain cases (socket crash)
+	 *	there is no Id as they have been purged from
+	 *	proxy_list, but there should still be a leftover
+	 *	packet hung off this request.
 	 */
 	RADIUS_PACKET old = *request->proxy;
+	int old_hash = request->in_proxy_hash;
 	home_server *home;
 	home_server *old_home = request->home_server;
 #ifdef WITH_TCP
@@ -2327,7 +2331,7 @@ static int request_proxy_anew(REQUEST *request)
 	}
 
 	/*
-	 *	Don't free the old Id on error.
+	 *	Don't free the old Id (if any) on error.
 	 */
 	if (!insert_into_proxy_hash(request)) {
 		radlog_request(L_PROXY, 0, request, "Failed to insert retransmission into the proxy list.");
@@ -2335,16 +2339,18 @@ static int request_proxy_anew(REQUEST *request)
 	}
 
 	/*
-	 *	Now that we have a new Id, free the old one
+	 *	Now that we have a new Id, free the old one (if any)
 	 *	and update the various statistics.
 	 */
 	PTHREAD_MUTEX_LOCK(&proxy_mutex);
-	fr_packet_list_yank(proxy_list, &old);
-	fr_packet_list_id_free(proxy_list, &old);
-	old_home->currently_outstanding--;
+	if (old_hash) {
+		fr_packet_list_yank(proxy_list, &old);
+		fr_packet_list_id_free(proxy_list, &old);
+		old_home->currently_outstanding--;
 #ifdef WITH_TCP
-	if (listener) listener->count--;
+		if (listener) listener->count--;
 #endif
+	}
 	PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
 
 	/*
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html

Reply via email to