summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2015-04-08 13:29:42 +0300
committerDmitry Stogov <dmitry@zend.com>2015-04-08 13:29:42 +0300
commit4d9a1883aa764e502990488d2e8b9c978be6fbd2 (patch)
tree1058bb04ebf8266a316c6449132e7cda7d0ce54b /main
parentfa795b05530c4ccd33ff63f23903bf4b458dc491 (diff)
downloadphp-git-4d9a1883aa764e502990488d2e8b9c978be6fbd2.tar.gz
Fixed bug #68887 (resources are not freed correctly)
Diffstat (limited to 'main')
-rw-r--r--main/php_streams.h1
-rw-r--r--main/streams/cast.c4
-rw-r--r--main/streams/streams.c11
3 files changed, 6 insertions, 10 deletions
diff --git a/main/php_streams.h b/main/php_streams.h
index 4f3d860a90..0ee3ff5458 100644
--- a/main/php_streams.h
+++ b/main/php_streams.h
@@ -284,6 +284,7 @@ PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream *
#define PHP_STREAM_FREE_RSRC_DTOR 8 /* called from the resource list dtor */
#define PHP_STREAM_FREE_PERSISTENT 16 /* manually freeing a persistent connection */
#define PHP_STREAM_FREE_IGNORE_ENCLOSING 32 /* don't close the enclosing stream instead */
+#define PHP_STREAM_FREE_KEEP_RSRC 64 /* keep associated zend_resource */
#define PHP_STREAM_FREE_CLOSE (PHP_STREAM_FREE_CALL_DTOR | PHP_STREAM_FREE_RELEASE_STREAM)
#define PHP_STREAM_FREE_CLOSE_CASTED (PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_PRESERVE_HANDLE)
#define PHP_STREAM_FREE_CLOSE_PERSISTENT (PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_PERSISTENT)
diff --git a/main/streams/cast.c b/main/streams/cast.c
index bc9cc805e8..23c59c71c0 100644
--- a/main/streams/cast.c
+++ b/main/streams/cast.c
@@ -86,7 +86,7 @@ static int stream_cookie_closer(void *cookie)
/* prevent recursion */
stream->fclose_stdiocast = PHP_STREAM_FCLOSE_NONE;
- return php_stream_close(stream);
+ return php_stream_free(stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_KEEP_RSRC);
}
#elif defined(HAVE_FOPENCOOKIE)
static ssize_t stream_cookie_reader(void *cookie, char *buffer, size_t size)
@@ -128,7 +128,7 @@ static int stream_cookie_closer(void *cookie)
/* prevent recursion */
stream->fclose_stdiocast = PHP_STREAM_FCLOSE_NONE;
- return php_stream_close(stream);
+ return php_stream_free(stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_KEEP_RSRC);
}
#endif /* elif defined(HAVE_FOPENCOOKIE) */
diff --git a/main/streams/streams.c b/main/streams/streams.c
index 886fc1da28..2358cc9df3 100644
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -439,15 +439,10 @@ fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remov
/* If not called from the resource dtor, remove the stream from the resource list. */
if ((close_options & PHP_STREAM_FREE_RSRC_DTOR) == 0 && stream->res) {
- /* zend_list_delete actually only decreases the refcount; if we're
- * releasing the stream, we want to actually delete the resource from
- * the resource list, otherwise the resource will point to invalid memory.
- * 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;
+ /* Close resource, but keep it in resource list */
zend_list_close(stream->res);
- if (!stream->__exposed) {
+ if ((close_options & PHP_STREAM_FREE_KEEP_RSRC) == 0) {
+ /* Completely delete zend_resource, if not referenced */
zend_list_delete(stream->res);
stream->res = NULL;
}