]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
STABLE12-h-gethost-r-race-20030401
authorDerrick Brashear <shadow@dementia.org>
Wed, 2 Apr 2003 01:23:58 +0000 (01:23 +0000)
committerDerrick Brashear <shadow@dementia.org>
Wed, 2 Apr 2003 01:23:58 +0000 (01:23 +0000)
FIXES 1308

Thanks to Chaskiel Grundman for explaining what was happening:
- the connection is old and pre-existing, but has no host structure.
- 2 calls come in
- the first one enters h_GetHost_r, and h_Lookup_r returns null (but identP is
non-null, since rx keeps it around until it gc's the connection)
  The first thread calls WhoAreYou, which succeeds, it then calls
InitCallBackState3 (after H_UNLOCK) note that the host has been inserted into
the hashtable
- the second thread enters h_GetHost_r, and calls rx_GetSpecific. it then
calls h_Lookup_r. h_Lookup_r will block (new host is locked), but eventually
returns the new host
- InitCallBackState3 returns, and the frees the old identP, replaces it, and
unlocks the host.
- the first thread returns from h_Lookup_r. boom.

the changes:
-call rx_GetSpecific after h_Lookup_r returns (and potentially slept)
-removes an if wrapping which always is true (since !interfValid is always
 true)
-don't realloc identP if it exists
-don't free an old one by calling rx_SetSpecific either

(cherry picked from commit 5967b22698c8aeb51131a62c56a2f7fbf1f8e79e)

src/viced/host.c

index 9310d26781b2a2df44a972d9309743978c205ee1..6f29850820abe750f439d9f2f26e1e7eda2d538c 100644 (file)
@@ -968,8 +968,8 @@ struct host *h_GetHost_r(tcon)
     hport = rxr_PortOf(tcon);
 retry:
     code = 0;
-    identP = (struct Identity *)rx_GetSpecific(tcon, rxcon_ident_key);
     host = h_Lookup_r(haddr, hport, &held);
+    identP = (struct Identity *)rx_GetSpecific(tcon, rxcon_ident_key);
     if (host && !identP && !(host->Console&1)) {
        /* This is a new connection, and we already have a host
         * structure for this address. Verify that the identity
@@ -1078,28 +1078,37 @@ retry:
         host = h_Alloc_r(tcon);
        h_gethostcps_r(host,FT_ApproxTime());
         if (!(host->Console&1)) {
-           if (!identP || !interfValid) {
-               H_UNLOCK
-               code = RXAFSCB_WhoAreYou(host->callback_rxcon, &interf);
-               H_LOCK
-               if ( code == RXGEN_OPCODE ) {
-                 identP = (struct Identity *)malloc(sizeof(struct Identity));
-                   identP->valid = 0;
+           int pident = 0;
+           H_UNLOCK
+           code = RXAFSCB_WhoAreYou(host->callback_rxcon, &interf);
+           H_LOCK
+           if ( code == RXGEN_OPCODE ) {
+               if (!identP)
+                   identP = (struct Identity *)malloc(sizeof(struct Identity));
+               else
+                   pident = 1;
+               identP->valid = 0;
+               if (!pident)
                    rx_SetSpecific(tcon, rxcon_ident_key, identP);
-                   ViceLog(25,
-                           ("Host %s:%d does not support WhoAreYou.\n",
-                           afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
-                   code = 0;
-               } else if (code == 0) {
-                   interfValid = 1;
+               ViceLog(25,
+                       ("Host %s:%d does not support WhoAreYou.\n",
+                        afs_inet_ntoa_r(host->host, hoststr), 
+                        ntohs(host->port)));
+               code = 0;
+           } else if (code == 0) {
+               if (!identP)
                    identP = (struct Identity *)malloc(sizeof(struct Identity));
-                   identP->valid = 1;
-                   identP->uuid = interf.uuid;
+               else
+                   pident = 1;
+               identP->valid = 1;
+               identP->uuid = interf.uuid;
+               if (!pident)
                    rx_SetSpecific(tcon, rxcon_ident_key, identP);
-                   ViceLog(25, ("WhoAreYou success on %s:%d\n",
-                               afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
-               }
+               ViceLog(25, ("WhoAreYou success on %s:%d\n",
+                            afs_inet_ntoa_r(host->host, hoststr), 
+                            ntohs(host->port)));
            }
+           interfValid=identP->valid;
            if (code == 0 && !identP->valid) {
                H_UNLOCK
                code = RXAFSCB_InitCallBackState(host->callback_rxcon);