]> granicus.if.org Git - php/commitdiff
Resource closing without destruction
authorDmitry Stogov <dmitry@zend.com>
Thu, 27 Feb 2014 08:28:55 +0000 (12:28 +0400)
committerDmitry Stogov <dmitry@zend.com>
Thu, 27 Feb 2014 08:28:55 +0000 (12:28 +0400)
Zend/zend_list.c
Zend/zend_list.h
main/streams/streams.c

index 8bc5161bda2e77363d5dc78f28174b8bb3002c37..f7cbfac89ff905883da68a5395aeb180febcc55a 100644 (file)
@@ -50,6 +50,37 @@ ZEND_API int _zend_list_delete(zend_resource *res TSRMLS_DC)
        }
 }
 
+ZEND_API int _zend_list_close(zend_resource *res TSRMLS_DC)
+{
+       if (res->gc.refcount <= 0) {
+               return zend_list_delete(res);
+       } else if (res->type >= 0) {
+               zend_rsrc_list_dtors_entry *ld;
+       
+               ld = zend_hash_index_find_ptr(&list_destructors, res->type);
+               if (ld) {
+                       switch (ld->type) {
+                               case ZEND_RESOURCE_LIST_TYPE_STD:
+                                       if (ld->list_dtor) {
+                                               (ld->list_dtor)(res->ptr);
+                                       }
+                                       break;
+                               case ZEND_RESOURCE_LIST_TYPE_EX:
+                                       if (ld->list_dtor_ex) {
+                                               ld->list_dtor_ex(res TSRMLS_CC);
+                                       }
+                                       break;
+                               EMPTY_SWITCH_DEFAULT_CASE()
+                       }
+               } else {
+                       zend_error(E_WARNING,"Unknown list entry type in request shutdown (%d)", res->type);
+               }
+               res->ptr = NULL;
+               res->type = -1;
+       }
+       return SUCCESS;
+}
+
 ZEND_API zend_resource* zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type TSRMLS_DC)
 {
        zval *zv;
@@ -124,26 +155,29 @@ ZEND_API void *zend_fetch_resource(zval *passed_id TSRMLS_DC, int default_id, co
 void list_entry_destructor(zval *zv)
 {
        zend_resource *res = Z_RES_P(zv);
-       zend_rsrc_list_dtors_entry *ld;
-       TSRMLS_FETCH();
+
+       if (res->type >= 0) {
+               zend_rsrc_list_dtors_entry *ld;
+               TSRMLS_FETCH();
        
-       ld = zend_hash_index_find_ptr(&list_destructors, res->type);
-       if (ld) {
-               switch (ld->type) {
-                       case ZEND_RESOURCE_LIST_TYPE_STD:
-                               if (ld->list_dtor) {
-                                       (ld->list_dtor)(res->ptr);
-                               }
-                               break;
-                       case ZEND_RESOURCE_LIST_TYPE_EX:
-                               if (ld->list_dtor_ex) {
-                                       ld->list_dtor_ex(res TSRMLS_CC);
-                               }
-                               break;
-                       EMPTY_SWITCH_DEFAULT_CASE()
+               ld = zend_hash_index_find_ptr(&list_destructors, res->type);
+               if (ld) {
+                       switch (ld->type) {
+                               case ZEND_RESOURCE_LIST_TYPE_STD:
+                                       if (ld->list_dtor) {
+                                               (ld->list_dtor)(res->ptr);
+                                       }
+                                       break;
+                               case ZEND_RESOURCE_LIST_TYPE_EX:
+                                       if (ld->list_dtor_ex) {
+                                               ld->list_dtor_ex(res TSRMLS_CC);
+                                       }
+                                       break;
+                               EMPTY_SWITCH_DEFAULT_CASE()
+                       }
+               } else {
+                       zend_error(E_WARNING,"Unknown list entry type in request shutdown (%d)", res->type);
                }
-       } else {
-               zend_error(E_WARNING,"Unknown list entry type in request shutdown (%d)", res->type);
        }
        efree(res);
 }
index 52b171e4222b89a7c78d1cbfb9397294bd0b5c6f..c58905aa1f295db3ba569e54093491f305976e6e 100644 (file)
@@ -66,8 +66,10 @@ void zend_destroy_rsrc_list_dtors(void);
 
 ZEND_API zval *zend_list_insert(void *ptr, int type TSRMLS_DC);
 ZEND_API int _zend_list_delete(zend_resource *res TSRMLS_DC);
+ZEND_API int _zend_list_close(zend_resource *res TSRMLS_DC);
 
 #define zend_list_delete(res)          _zend_list_delete(res TSRMLS_CC)
+#define zend_list_close(res)           _zend_list_close(res TSRMLS_CC)
 
 ZEND_API zend_resource *zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type TSRMLS_DC);
 ZEND_API void *zend_fetch_resource(zval *passed_id TSRMLS_DC, int default_id, const char *resource_type_name, int *found_resource_type, int num_resource_types, ...);
index e80a87c860e6d22f2686957275afce313a047a29..c595c802405fe522f513adf84fcb341b979a5d50 100644 (file)
@@ -464,8 +464,8 @@ fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remov
                 * In any case, let's always completely delete it from the resource list,
                 * not only when PHP_STREAM_FREE_RELEASE_STREAM is set */
 //???          while (zend_list_delete(stream->res) == SUCCESS) {}
-               stream->res->gc.refcount = 0;
-               zend_list_delete(stream->res);
+//???          stream->res->gc.refcount = 0;
+               zend_list_close(stream->res);
        }
 
        if (close_options & PHP_STREAM_FREE_CALL_DTOR) {