<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -161,6 +161,7 @@ static void remove_from_request_hash(REQUEST *request)
 #ifdef WITH_PROXY
 static REQUEST *lookup_in_proxy_hash(RADIUS_PACKET *reply)
 {
+	int done = FALSE;
 	RADIUS_PACKET **proxy_p;
 	REQUEST *request;
 
@@ -173,23 +174,17 @@ static REQUEST *lookup_in_proxy_hash(RADIUS_PACKET *reply)
 	}
 
 	request = fr_packet2myptr(REQUEST, proxy, proxy_p);
+	request-&gt;num_proxied_responses++; /* needs to be protected by lock */
 
-	if (!request) {
-		PTHREAD_MUTEX_UNLOCK(&amp;proxy_mutex);
-		return NULL;
-	}
+	done = (request-&gt;num_proxied_requests == request-&gt;num_proxied_responses);
+	PTHREAD_MUTEX_UNLOCK(&amp;proxy_mutex);
 
-	request-&gt;num_proxied_responses++;
 
 	/*
 	 *	Catch the most common case of everything working
 	 *	correctly.
 	 */
-	if (request-&gt;num_proxied_requests == request-&gt;num_proxied_responses) {
-		remove_from_proxy_hash(request);
-	}
-
-	PTHREAD_MUTEX_UNLOCK(&amp;proxy_mutex);
+	if (done) remove_from_proxy_hash(request);
 
 	return request;
 }
@@ -361,69 +356,47 @@ static int remove_all_proxied_requests(void *ctx, void *data)
 
 
 #ifdef WITH_PROXY
-static int proxy_id_alloc(REQUEST *request, RADIUS_PACKET *packet)
-{
-	void *proxy_listener;
-
-	if (fr_packet_list_id_alloc(proxy_list, request-&gt;home_server-&gt;proto,
-				    packet, &amp;proxy_listener)) {
-		request-&gt;proxy_listener = proxy_listener;
-		return 1;
-	}
-
-	if (!proxy_new_listener(request-&gt;home_server, 0)) {
-		RDEBUG2(&quot;ERROR: Failed to create a new socket for proxying requests.&quot;);
-		return 0;
-	}
-
-	if (!fr_packet_list_id_alloc(proxy_list, request-&gt;home_server-&gt;proto,
-				     packet, &amp;proxy_listener)) {
-		RDEBUG2(&quot;ERROR: Failed allocating Id for new socket when proxying requests.&quot;);
-		return 0;
-	}
-	
-	request-&gt;proxy_listener = proxy_listener;
-	return 1;
-}
-
-
-static int insert_into_proxy_hash(REQUEST *request, int retransmit)
+static int insert_into_proxy_hash(REQUEST *request)
 {
 	char buf[128];
+	int rcode, tries;
+	void *proxy_listener;
 
 	rad_assert(request-&gt;proxy != NULL);
 	rad_assert(proxy_list != NULL);
 
+	tries = 1;
+retry:
 	PTHREAD_MUTEX_LOCK(&amp;proxy_mutex);
-
-	if (!retransmit) {
-		if (!proxy_id_alloc(request, request-&gt;proxy)) {
-			PTHREAD_MUTEX_UNLOCK(&amp;proxy_mutex);
+	rcode = fr_packet_list_id_alloc(proxy_list,
+					request-&gt;home_server-&gt;proto,
+					request-&gt;proxy, &amp;proxy_listener);
+	PTHREAD_MUTEX_UNLOCK(&amp;proxy_mutex);
+	
+	if (!rcode) {
+		/*
+		 *	Also locks the proxy mutex, so we have to call
+		 *	it with the mutex unlocked.  Some systems
+		 *	don't support recursive mutexes.
+		 */
+		if (!proxy_new_listener(request-&gt;home_server, 0)) {
+			RDEBUG2(&quot;ERROR: Failed to create a new socket for proxying requests.&quot;);
 			return 0;
 		}
-	} else {
-		RADIUS_PACKET packet;
+		request-&gt;proxy-&gt;src_port = 0; /* Use any new socket */
 
-#ifdef WITH_TCP
-		rad_assert(request-&gt;home_server-&gt;proto != IPPROTO_TCP);
-#endif
-
-		packet = *request-&gt;proxy;
-
-		if (!proxy_id_alloc(request, &amp;packet)) {
-			PTHREAD_MUTEX_UNLOCK(&amp;proxy_mutex);
+		tries++;
+		if (tries &gt; 2) {
+			RDEBUG2(&quot;ERROR: Failed allocating Id for new socket when proxying requests.&quot;);
 			return 0;
 		}
-
-		/*
-		 *	Yank the request, free the old Id, and
-		 *	remember the new Id.
-		 */
-		fr_packet_list_yank(proxy_list, request-&gt;proxy);
-		fr_packet_list_id_free(proxy_list, request-&gt;proxy);
-		*request-&gt;proxy = packet;
+		
+		goto retry;
 	}
 
+	request-&gt;proxy_listener = proxy_listener;
+
+	PTHREAD_MUTEX_LOCK(&amp;proxy_mutex);
 	if (!fr_packet_list_insert(proxy_list, &amp;request-&gt;proxy)) {
 		fr_packet_list_id_free(proxy_list, request-&gt;proxy);
 		PTHREAD_MUTEX_UNLOCK(&amp;proxy_mutex);
@@ -822,7 +795,7 @@ static void ping_home_server(void *ctx)
 
 	rad_assert(request-&gt;proxy_listener == NULL);
 
-	if (!insert_into_proxy_hash(request, FALSE)) {
+	if (!insert_into_proxy_hash(request)) {
 		RDEBUG2(&quot;ERROR: Failed inserting status check %d into proxy hash.  Discarding it.&quot;,
 		       request-&gt;number);
 		ev_request_free(&amp;request);
@@ -1486,11 +1459,29 @@ static void retransmit_coa_request(void *ctx)
 	}
 	
 	if (update_event_timestamp(request-&gt;proxy, now.tv_sec)) {
-		if (!insert_into_proxy_hash(request, TRUE)) {
+		/*
+		 *	Keep a copy of the old Id so that the
+		 *	re-transmitted request doesn't re-use the old
+		 *	Id.
+		 */
+		RADIUS_PACKET old = *request-&gt;proxy;
+
+		/*
+		 *	Don't free the old Id on error.
+		 */
+		if (!insert_into_proxy_hash(request)) {
 			DEBUG(&quot;ERROR: Failed re-inserting CoA request into proxy hash.&quot;);
 			return;
 		}
 
+		/*
+		 *	Now that we have a new Id, free the old one.
+		 */
+		PTHREAD_MUTEX_LOCK(&amp;proxy_mutex);
+		fr_packet_list_yank(proxy_list, &amp;old);
+		fr_packet_list_id_free(proxy_list, &amp;old);
+		PTHREAD_MUTEX_UNLOCK(&amp;proxy_mutex);
+
 		request-&gt;num_proxied_requests = 0;
 		request-&gt;num_proxied_responses = 0;
 	}
@@ -1674,7 +1665,7 @@ static int originated_coa_request(REQUEST *request)
 	coa-&gt;proxy-&gt;dst_ipaddr = coa-&gt;home_server-&gt;ipaddr;
 	coa-&gt;proxy-&gt;dst_port = coa-&gt;home_server-&gt;port;
 
-	if (!insert_into_proxy_hash(coa, FALSE)) {
+	if (!insert_into_proxy_hash(coa)) {
 		DEBUG(&quot;ERROR: Failed inserting CoA request into proxy hash.&quot;);
 		goto fail;
 	}
@@ -1923,7 +1914,7 @@ static int proxy_request(REQUEST *request)
 		return 0;
 	}
 
-	if (!insert_into_proxy_hash(request, FALSE)) {
+	if (!insert_into_proxy_hash(request)) {
 		RDEBUG(&quot;ERROR: Failed inserting request into proxy hash.&quot;);
 		return 0;
 	}
@@ -3660,7 +3651,7 @@ static void handle_signal_self(int flag)
 
 #ifdef WITH_PROXY
 	/*
-	 *	Add event handlers for idle timeouts &amp;&amp; maximum lifetime.XXX
+	 *	Add event handlers for idle timeouts &amp;&amp; maximum lifetime.
 	 */
 	if ((flag &amp; RADIUS_SIGNAL_SELF_NEW_FD) != 0) {
 		struct timeval when;
@@ -3895,8 +3886,6 @@ int radius_event_init(CONF_SECTION *cs, int spawn_flag)
 
 #ifdef WITH_PROXY
 	if (mainconfig.proxy_requests) {
-		pthread_mutexattr_t attr;
-
 		/*
 		 *	Create the tree for managing proxied requests and
 		 *	responses.
@@ -3905,23 +3894,11 @@ int radius_event_init(CONF_SECTION *cs, int spawn_flag)
 		if (!proxy_list) return 0;
 
 #ifdef HAVE_PTHREAD_H
-		pthread_mutexattr_init(&amp;attr);
-
-#ifdef PTHREAD_MUTEX_RECURSIVE
-		if (pthread_mutexattr_settype(&amp;attr, PTHREAD_MUTEX_RECURSIVE) &lt; 0) {
-			radlog(L_ERR, &quot;FATAL: Failed to set type for proxy mutex: %s&quot;,
-			       strerror(errno));
-			exit(1);
-		}
-#endif
-
-		if (pthread_mutex_init(&amp;proxy_mutex, &amp;attr) != 0) {
+		if (pthread_mutex_init(&amp;proxy_mutex, NULL) != 0) {
 			radlog(L_ERR, &quot;FATAL: Failed to initialize proxy mutex: %s&quot;,
 			       strerror(errno));
 			exit(1);
 		}
-
-		pthread_mutexattr_destroy(&amp;attr);
 #endif
 	}
 #endif
@@ -4056,9 +4033,7 @@ void radius_event_free(void)
 	 *	referenced from anywhere else.  Remove them first.
 	 */
 	if (proxy_list) {
-		PTHREAD_MUTEX_LOCK(&amp;proxy_mutex);
 		fr_packet_list_walk(proxy_list, NULL, proxy_hash_cb);
-		PTHREAD_MUTEX_UNLOCK(&amp;proxy_mutex);
 		fr_packet_list_free(proxy_list);
 		proxy_list = NULL;
 	}</diff>
      <filename>src/main/event.c</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>d9dd62aae7baa5346f19236cead4414c03546d45</id>
    </parent>
  </parents>
  <author>
    <name>Alan T. DeKok</name>
    <email>aland@freeradius.org</email>
  </author>
  <url>http://github.com/alandekok/freeradius-server/commit/8fa1a08726aad4f379c7bcc6df608f8d79594a34</url>
  <id>8fa1a08726aad4f379c7bcc6df608f8d79594a34</id>
  <committed-date>2009-10-21T06:16:54-07:00</committed-date>
  <authored-date>2009-10-21T06:15:28-07:00</authored-date>
  <message>Removed recursive mutexes.

Some systems don't support recursive mutexes.  Instead, they hang.
So... we've got to re-write the code so that it doesn't depend on
recursive mutexes.</message>
  <tree>cfc93570f6a6037c9aa271ada1453e59ce73569c</tree>
  <committer>
    <name>Alan T. DeKok</name>
    <email>aland@freeradius.org</email>
  </committer>
</commit>
