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 {

-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to