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;