Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!husc6!mit-eddie!ll-xn!ames!sdcsvax!ucbvax!ZERMATT.LCS.MIT.EDU!RWS From: RWS@ZERMATT.LCS.MIT.EDU (Robert Scheifler) Newsgroups: comp.windows.x Subject: V11 fix #28, server/dix/resource.c, FreeResource won't free all classes of a resource Message-ID: <871022082138.7.RWS@KILLINGTON.LCS.MIT.EDU> Date: Thu, 22-Oct-87 08:21:00 EDT Article-I.D.: KILLINGT.871022082138.7.RWS Posted: Thu Oct 22 08:21:00 1987 Date-Received: Sun, 25-Oct-87 00:49:08 EDT References: <8710151826.AA23827@sloth.Berkeley.EDU> Sender: daemon@ucbvax.BERKELEY.EDU Organization: The ARPA Internet Lines: 103 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;