callback-rxcon-protection-20031114
authorDerrick Brashear <shadow@dementia.org>
Sat, 15 Nov 2003 03:08:10 +0000 (03:08 +0000)
committerDerrick Brashear <shadow@dementia.org>
Sat, 15 Nov 2003 03:08:10 +0000 (03:08 +0000)
FIXES 2498

        CheckHost() sets the HOSTDELETED flag on a host, does its
        touch, calls H_UNLOCK at the end of its function;
        AddCallBCal1 in a different thread grabs the lock, does its
        thing.  Gets to GetSomeSpace_r(), which calls
        h_Enumerate_r; the host in question isn't held, so
        h_Enumerate_r calls h_Hold_r and h_Release_r on the host
        that CheckHost() set the HOSTDELETED flag on; h_Release_r
        sees the HOSTDELETED flag and calls h_TossStuff_r, poof, we
        have our broken host entry for ClearHostCallbacks_r to trip

src/viced/callback.c

index 10e8e9e..55af2b9 100644 (file)
@@ -1534,16 +1534,22 @@ CleanupTimedOutCallBacks_r(void)
 }
 
 static struct host *lih_host;
+static int lih_host_held = 0;
 
 static int
 lih_r(register struct host *host, register int held,
       register struct host *hostp)
 {
+    lih_host_held = 0;
     if (host->cblist
        && ((hostp && host != hostp) || (!held && !h_OtherHolds_r(host)))
        && (!lih_host || host->ActiveCall < lih_host->ActiveCall)) {
        lih_host = host;
     }
+    if (!held) {
+       held = 1;
+       lih_host_held = 1;
+    }
     return held;
 }
 
@@ -1571,8 +1577,13 @@ GetSomeSpace_r(struct host *hostp, int locked)
        hp = lih_host;
        if (hp) {
            cbstuff.GSS4++;
-           if (!ClearHostCallbacks_r(hp, 0 /* not locked or held */ ))
+           if (!ClearHostCallbacks_r(hp, 0 /* not locked or held */ )) {
+               if (lih_host_held) 
+                   h_Release_r(hp);
                return 0;
+           }
+           if (lih_host_held) 
+               h_Release_r(hp);
            hp2 = hp->next;
        } else {
            hp2 = hostList;