RWS@ZERMATT.LCS.MIT.EDU (Robert Scheifler) (10/22/87)
Date: Thu, 15 Oct 87 11:26:04 PDT From: deboor%sloth.Berkeley.EDU@berkeley.edu (Adam de Boor) SYNOPSIS: If there is more than one class of resource under a given resource ID, FreeResource() will only free the first resource it encounters. DESCRIPTION: Because FreeResource() breaks out of the loop once it has freed a single resource, rather than proceeding to the end of the chain, if there is more than one class for a single resource id (as is done for windows in the sun server), the previous resource will remain. FIX: It should be noted as a caveat that the DeleteFunc for a resource is not allowed to call AddResource (although it is permitted to recall FreeResource). in server/dix/resource.c: *** /tmp/,RCSt1003320 Thu Oct 22 08:14:34 1987 --- resource.c Wed Oct 21 09:26:27 1987 *************** *** 22,28 **** ********************************************************/ ! /* $Header: resource.c,v 1.62 87/09/04 11:45:57 toddb Exp $ */ /* Routines to manage various kinds of resources: * --- 22,28 ---- ********************************************************/ ! /* $Header: resource.c,v 1.63 87/10/21 09:25:11 rws Exp $ */ /* Routines to manage various kinds of resources: * *************** *** 223,251 **** { unsigned cid; register ResourcePtr res; ! ResourcePtr * head; ! Bool gotOne = FALSE; if (((cid = CLIENT_ID(id)) < MaxClients) && clientTable[cid].buckets) { head = &clientTable[cid].resources[Hash(cid, id)]; ! for (res = *head; res; res = *head) { if (res->id == id) { ! *head = res->next; ! clientTable[cid].elements--; if (res->type & CACHEDTYPES) FlushClientCaches(res->id); if (skipDeleteFuncClass != res->class) (*res->DeleteFunc) (res->value, res->id); Xfree(res); gotOne = TRUE; - break; } else ! head = &res->next; } if(clients[cid] && (id == clients[cid]->lastDrawableID)) clients[cid]->lastDrawableID = INVALID; --- 223,256 ---- { unsigned cid; register ResourcePtr res; ! register ResourcePtr *prev, *head; ! register int *eltptr; ! int elements; ! Bool gotOne = FALSE; if (((cid = CLIENT_ID(id)) < MaxClients) && clientTable[cid].buckets) { head = &clientTable[cid].resources[Hash(cid, id)]; + eltptr = &clientTable[cid].elements; ! prev = head; ! while (res = *prev) { if (res->id == id) { ! *prev = res->next; ! elements = --*eltptr; if (res->type & CACHEDTYPES) FlushClientCaches(res->id); if (skipDeleteFuncClass != res->class) (*res->DeleteFunc) (res->value, res->id); Xfree(res); + if (*eltptr != elements) + prev = head; /* prev may no longer be valid */ gotOne = TRUE; } else ! prev = &res->next; } if(clients[cid] && (id == clients[cid]->lastDrawableID)) clients[cid]->lastDrawableID = INVALID;