Minor changes in "remove from proxy hash"
authorAlan T. DeKok <aland@freeradius.org>
Fri, 8 May 2009 12:49:39 +0000 (14:49 +0200)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 8 May 2009 12:49:39 +0000 (14:49 +0200)
This avoids esoteric race conditions that no one has seen in practice

src/main/event.c

index e9a149a..0880fd5 100644 (file)
@@ -199,9 +199,24 @@ static REQUEST *lookup_in_proxy_hash(RADIUS_PACKET *reply)
 
 static void remove_from_proxy_hash(REQUEST *request)
 {
+       /*
+        *      Check this without grabbing the mutex because it's a
+        *      lot faster that way.
+        */
        if (!request->in_proxy_hash) return;
 
+       /*
+        *      The "not in hash" flag is definitive.  However, if the
+        *      flag says that it IS in the hash, there might still be
+        *      a race condition where it isn't.
+        */
        PTHREAD_MUTEX_LOCK(&proxy_mutex);
+
+       if (!request->in_proxy_hash) {
+               PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
+               return;
+       }
+
        fr_packet_list_yank(proxy_list, request->proxy);
        fr_packet_list_id_free(proxy_list, request->proxy);
 
@@ -216,9 +231,14 @@ static void remove_from_proxy_hash(REQUEST *request)
                request->home_server->currently_outstanding--;
        }
 
-       PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
-
+       /*
+        *      Got from YES in hash, to NO, not in hash while we hold
+        *      the mutex.  This guarantees that when another thread
+        *      grans the mutex, the "not in hash" flag is correct.
+        */
        request->in_proxy_hash = FALSE;
+
+       PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
 }
 
 static int proxy_id_alloc(REQUEST *request, RADIUS_PACKET *packet)
@@ -352,6 +372,8 @@ static int insert_into_proxy_hash(REQUEST *request, int retransmit)
                return 0;
        }
 
+       request->in_proxy_hash = TRUE;
+
        PTHREAD_MUTEX_UNLOCK(&proxy_mutex);
 
        RDEBUG3(" proxy: allocating destination %s port %d - Id %d",
@@ -360,8 +382,6 @@ static int insert_into_proxy_hash(REQUEST *request, int retransmit)
               request->proxy->dst_port,
               request->proxy->id);
 
-       request->in_proxy_hash = TRUE;
-
        return 1;
 }