PATCH to zend_list.c
| From: | Thies C. Arntzen | Date: | Tue, 16 Apr 2002 15:19:20 +0000 |
| Subject: | PATCH to zend_list.c | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-82848@lists.php.net to get a copy of this message | ||
zeev, andi
i have to following problem:
while the zend_destroy_rsrc_list() is running a _dtor
function for one of my resources it (the dtor of the resource)
does a zend_list_delete, which does a hash_find on the
resource-list again. the problem is that
zend_destroy_rsrc_list takes out the bucked it will dtor from
the hash's mail linked list but it leaves the bucket in
ht->arBuckets. so my zend_list_delete might find an already
dealloced entry (cause the resource_list is inconsistent) ->
boom!
the attached patch fixes this by removing the bucket not only
from the hashes global linked list but by also removing all
traces of it from the ht->arBuckets.
i have stolen some code from zend_hash_del_key_or_index.
so - we could either apply this patch as it is
as zend_destroy_rsrc_list() already fiddles with
hash-internals -or- i create a macro in zend_hash.h
called DISCONNECT_BUCKET_FROM_ARLIST(ht, bucket).
a patch along these lines is needed to have a consistent
resource_list while the _dtors are called. i don't think
we'll see a measuarable speed impact once this patch is in.
comments?
tc
? .zend_hash.c.swp Index: zend_list.c =================================================================== RCS file: /repository/Zend/zend_list.c,v retrieving revision 1.52 diff -u -r1.52 zend_list.c --- zend_list.c 6 Jan 2002 15:21:09 -0000 1.52 +++ zend_list.c 16 Apr 2002 15:17:12 -0000 @@ -231,8 +231,10 @@ void zend_destroy_rsrc_list(HashTable *ht TSRMLS_DC) { Bucket *p, *q; + uint nIndex; while (1) { + /* remove bucket from main linked-list */ p = ht->pListTail; if (!p) { break; @@ -242,6 +244,34 @@ q->pListNext = NULL; } ht->pListTail = q; + + /* stolen from zend_hash_del_key_or_index - should be moved back into zend_hash */ + nIndex = p->h & ht->nTableMask; + + if (p == ht->arBuckets[nIndex]) { + ht->arBuckets[nIndex] = p->pNext; + } else { + p->pLast->pNext = p->pNext; + } + if (p->pNext) { + p->pNext->pLast = p->pLast; + } + if (p->pListLast != NULL) { + p->pListLast->pListNext = p->pListNext; + } else { + /* Deleting the head of the list */ + ht->pListHead = p->pListNext; + } + if (p->pListNext != NULL) { + p->pListNext->pListLast = p->pListLast; + } else { + ht->pListTail = p->pListLast; + } + if (ht->pInternalPointer == p) { + ht->pInternalPointer = p->pListNext; + } + ht->nNumOfElements--; + /* now the hashtable is consistent again */ if (ht->pDestructor) { zend_try {
? .zend_hash.c.swp Index: zend_list.c =================================================================== RCS file: /repository/Zend/zend_list.c,v retrieving revision 1.52 diff -u -r1.52 zend_list.c --- zend_list.c 6 Jan 2002 15:21:09 -0000 1.52 +++ zend_list.c 16 Apr 2002 15:17:12 -0000 @@ -231,8 +231,10 @@ void zend_destroy_rsrc_list(HashTable *ht TSRMLS_DC) { Bucket *p, *q; + uint nIndex; while (1) { + /* remove bucket from main linked-list */ p = ht->pListTail; if (!p) { break; @@ -242,6 +244,34 @@ q->pListNext = NULL; } ht->pListTail = q; + + /* stolen from zend_hash_del_key_or_index - should be moved back into zend_hash */ + nIndex = p->h & ht->nTableMask; + + if (p == ht->arBuckets[nIndex]) { + ht->arBuckets[nIndex] = p->pNext; + } else { + p->pLast->pNext = p->pNext; + } + if (p->pNext) { + p->pNext->pLast = p->pLast; + } + if (p->pListLast != NULL) { + p->pListLast->pListNext = p->pListNext; + } else { + /* Deleting the head of the list */ + ht->pListHead = p->pListNext; + } + if (p->pListNext != NULL) { + p->pListNext->pListLast = p->pListLast; + } else { + ht->pListTail = p->pListLast; + } + if (ht->pInternalPointer == p) { + ht->pInternalPointer = p->pListNext; + } + ht->nNumOfElements--; + /* now the hashtable is consistent again */ if (ht->pDestructor) { zend_try {