]> granicus.if.org Git - php/commitdiff
Streams are all tracked as resources now.
authorWez Furlong <wez@php.net>
Wed, 20 Mar 2002 14:21:30 +0000 (14:21 +0000)
committerWez Furlong <wez@php.net>
Wed, 20 Mar 2002 14:21:30 +0000 (14:21 +0000)
Add some logic that will help track down leaks
when debug is enabled.

ext/exif/exif.c
ext/pgsql/pgsql.c
ext/standard/exec.c
ext/standard/file.c
ext/standard/fsock.c
ext/standard/image.c
ext/zlib/zlib.c
main/php_streams.h
main/streams.c
main/user_streams.c

index 7fdf6c9f8781c8565e93b0a13505438e286b4101..86aab274977ee5ba1b70b3ac4b06c76221f021d8 100644 (file)
@@ -3254,7 +3254,6 @@ PHP_FUNCTION(exif_imagetype)
 {
        zval **arg1;
        php_stream * stream;
-       int rsrc_id;
        int itype = 0;
 
        if (ZEND_NUM_ARGS() != 1)
@@ -3269,11 +3268,9 @@ PHP_FUNCTION(exif_imagetype)
                RETURN_FALSE;
        }
 
-       rsrc_id = ZEND_REGISTER_RESOURCE(NULL, stream, php_file_le_stream());
-
        itype = itype = php_getimagetype(stream, NULL TSRMLS_CC);
 
-       zend_list_delete(rsrc_id);
+       php_stream_close(stream);
 
        if ( itype == IMAGE_FILETYPE_UNKNOWN) {
                RETURN_FALSE;
index e82379127e76cbf34224015e518926dfc69345e5..6e870c20b0a996ed5fda9e191e989315e2753f18 100644 (file)
@@ -1478,7 +1478,7 @@ PHP_FUNCTION(pg_trace)
                php_stream_close(stream);
                RETURN_FALSE;
        }
-       ZEND_REGISTER_RESOURCE(NULL, stream, php_file_le_stream());
+       php_stream_auto_cleanup(stream);
        PQtrace(pgsql, fp);
        RETURN_TRUE;
 }
index f5f337fee596eb91bfb09882053489ed1b61255e..4b6b75c768dd864bd7db333e656efd90c5ed1d79 100644 (file)
@@ -49,7 +49,6 @@ int php_Exec(int type, char *cmd, pval *array, pval *return_value TSRMLS_DC)
        int buflen = 0;
        int t, l, output=1;
        int overflow_limit, lcmd, ldir;
-       int rsrc_id;
        char *b, *c, *d=NULL;
        php_stream *stream = NULL;
 #if PHP_SIGCHILD
@@ -143,8 +142,6 @@ int php_Exec(int type, char *cmd, pval *array, pval *return_value TSRMLS_DC)
         */
 
        stream = php_stream_fopen_from_pipe(fp, "rb");
-       if (stream)
-               rsrc_id = ZEND_REGISTER_RESOURCE(NULL, stream, php_file_le_stream());
 
        if (type != 3) {
                l=0;
@@ -219,8 +216,7 @@ int php_Exec(int type, char *cmd, pval *array, pval *return_value TSRMLS_DC)
                }
        }
 
-       /* the zend_list_delete will pclose our popen'ed process */
-       zend_list_delete(rsrc_id); 
+       php_stream_close(stream); 
 
 #if HAVE_SYS_WAIT_H
        if (WIFEXITED(FG(pclose_ret))) {
index a58b511902eaf3d4390ff7ef3f5c416e0fa751a5..cf76315f2bc83d9265733742c7383f1054ed7897 100644 (file)
@@ -113,7 +113,7 @@ static void _file_stream_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 {
        php_stream *stream = (php_stream*)rsrc->ptr;
        /* the stream might be a pipe, so set the return value for pclose */
-       FG(pclose_ret) = php_stream_close(stream);
+       FG(pclose_ret) = php_stream_free(stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR);
 }
 
 PHPAPI int php_file_le_stream(void)
@@ -528,7 +528,7 @@ PHP_NAMED_FUNCTION(php_if_tmpfile)
        stream = php_stream_fopen_tmpfile();
 
        if (stream)     {
-               ZEND_REGISTER_RESOURCE(return_value, stream, le_stream);
+               php_stream_to_zval(stream, return_value);
        }
        else    {
                RETURN_FALSE;
@@ -593,7 +593,9 @@ PHP_NAMED_FUNCTION(php_if_fopen)
                RETURN_FALSE;
        }
        FG(fgetss_state) = 0;
-       ZEND_REGISTER_RESOURCE(return_value, stream, le_stream);
+
+       php_stream_to_zval(stream, return_value);
+
        return;
 }
 /* }}} */
@@ -676,9 +678,9 @@ PHP_FUNCTION(popen)
        if (stream == NULL)     {
                zend_error(E_WARNING, "popen(\"%s\", \"%s\"): %s", Z_STRVAL_PP(arg1), p, strerror(errno));
                RETVAL_FALSE;
+       } else {
+               php_stream_to_zval(stream, return_value);
        }
-       else
-               ZEND_REGISTER_RESOURCE(return_value, stream, le_stream);
 
        efree(p);
 }
index 84a12eb9fc150c3649077b7732c3386bab2ed38e..21eb6e8256e34e114fcafc84cf6ec4e1a2e66704 100644 (file)
@@ -141,7 +141,7 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                                (void *) &stream) == SUCCESS)
        {
                efree(hashkey);
-               ZEND_REGISTER_RESOURCE(return_value, stream, php_file_le_stream());
+               php_stream_to_zval(stream, return_value);
                return;
        }
 
@@ -241,7 +241,7 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                RETURN_FALSE;
        }
                
-       ZEND_REGISTER_RESOURCE(return_value, stream, php_file_le_stream());
+       php_stream_to_zval(stream, return_value);
 }
 
 /* }}} */
index 9d6896c608e22b906e323fec35c1070418f4e378..f12c8cb39e95414b7c9e660acfbcfd18e50ecfaa 100644 (file)
@@ -684,7 +684,6 @@ PHPAPI int php_getimagetype(php_stream * stream, char *filetype TSRMLS_DC)
 PHP_FUNCTION(getimagesize)
 {
        zval **arg1, **info = NULL;
-       int rsrc_id;
        int itype = 0;
        char temp[64];
        struct gfxinfo *result = NULL;
@@ -723,8 +722,6 @@ PHP_FUNCTION(getimagesize)
                RETURN_FALSE;
        }
 
-       rsrc_id = ZEND_REGISTER_RESOURCE(NULL, stream, php_file_le_stream());
-
        itype = php_getimagetype(stream, NULL TSRMLS_CC);
        switch( itype) {
         case IMAGE_FILETYPE_GIF:
@@ -763,7 +760,7 @@ PHP_FUNCTION(getimagesize)
                break;
        }
 
-       zend_list_delete(rsrc_id);
+       php_stream_close(stream);
 
        if (result) {
                if (array_init(return_value) == FAILURE) {
index f4323a8b8be5035eb1855915cb2eb265814d01cd..9c46953f831f074530c4eca69d32186543a8a880 100644 (file)
@@ -255,15 +255,9 @@ static gzFile php_gzopen_wrapper(char *path, char *mode, int options TSRMLS_DC)
 
        stream = php_stream_open_wrapper(path, mode, options | REPORT_ERRORS, NULL);
        if (stream)     {
-               if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD|PHP_STREAM_CAST_TRY_HARD, (void**)&fd, 1))
+               if (SUCCESS == php_stream_cast(stream, PHP_STREAM_CAST_RELEASE|PHP_STREAM_AS_FD|PHP_STREAM_CAST_TRY_HARD, (void**)&fd, 1))
                {
-                       gzFile ret = gzdopen(fd, mode);
-                       if (ret)        {
-                               /* arrange to clean up the actual stream */
-                               ZEND_REGISTER_RESOURCE(NULL, stream, php_file_le_stream());
-/*                             php_stream_auto_cleanup(stream); */
-                               return ret;
-                       }
+                       return gzdopen(fd, mode);
                }
                php_stream_close(stream);
        }
index 98a62286f8e62dc59851803be076c527ff477fac..4a63edcd5c395909a84499a1bd2c64895d3b836d 100755 (executable)
@@ -120,10 +120,15 @@ struct _php_stream  {
 
        int is_persistent;
        char mode[16];                  /* "rwb" etc. ala stdio */
+       int rsrc_id;                    /* used for auto-cleanup */
+       int in_free;                    /* to prevent recursion during free */
        /* so we know how to clean it up correctly.  This should be set to
         * PHP_STREAM_FCLOSE_XXX as appropriate */
        int fclose_stdiocast;
        FILE *stdiocast;    /* cache this, otherwise we might leak! */
+#if ZEND_DEBUG
+       int __exposed;  /* non-zero if exposed as a zval somewhere */
+#endif
 }; /* php_stream */
 /* state definitions when closing down; these are private to streams.c */
 #define PHP_STREAM_FCLOSE_NONE 0
@@ -135,9 +140,24 @@ PHPAPI php_stream *_php_stream_alloc(php_stream_ops *ops, void *abstract,
                int persistent, const char *mode STREAMS_DC TSRMLS_DC);
 #define php_stream_alloc(ops, thisptr, persistent, mode)       _php_stream_alloc((ops), (thisptr), (persistent), (mode) STREAMS_CC TSRMLS_CC)
 
+#define php_stream_get_resource_id(stream)             (stream)->rsrc_id
+
+#if ZEND_DEBUG
+/* use this to tell the stream that it is OK if we don't explicitly close it */
+# define php_stream_auto_cleanup(stream)       { (stream)->__exposed++; }
+/* use this to assign the stream to a zval and tell the stream that is
+ * has been exported to the engine; it will expect to be closed automatically
+ * when the resources are auto-destructed */
+# define php_stream_to_zval(stream, zval)      { ZVAL_RESOURCE(zval, (stream)->rsrc_id); (stream)->__exposed++; }
+#else
+# define php_stream_auto_cleanup(stream)       /* nothing */
+# define php_stream_to_zval(stream, zval)      { ZVAL_RESOURCE(zval, (stream)->rsrc_id); }
+#endif
+
 #define PHP_STREAM_FREE_CALL_DTOR                      1 /* call ops->close */
 #define PHP_STREAM_FREE_RELEASE_STREAM         2 /* pefree(stream) */
 #define PHP_STREAM_FREE_PRESERVE_HANDLE                4 /* tell ops->close to not close it's underlying handle */
+#define PHP_STREAM_FREE_RSRC_DTOR                      8 /* called from the resource list dtor */
 #define PHP_STREAM_FREE_CLOSE                          (PHP_STREAM_FREE_CALL_DTOR | PHP_STREAM_FREE_RELEASE_STREAM)
 PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC);
 #define php_stream_free(stream, close_options) _php_stream_free((stream), (close_options) TSRMLS_CC)
index 687535e4b9eaa1e9fafae91003bbd7a5002f29f9..419745b9d4639dbdd6ba517b148a3c485479ac9d 100755 (executable)
@@ -25,6 +25,7 @@
 #include "php_globals.h"
 #include "php_network.h"
 #include "php_open_temporary_file.h"
+#include "ext/standard/file.h"
 
 #ifdef HAVE_SYS_MMAN_H
 #include <sys/mman.h>
@@ -35,6 +36,7 @@
 #endif
 
 #define CHUNK_SIZE     8192
+#define PHP_STREAM_MAX_MEM     2 * 1024 * 1024
 
 #ifdef PHP_WIN32
 #define EWOULDBLOCK WSAEWOULDBLOCK
@@ -78,7 +80,7 @@ PHPAPI php_stream *_php_stream_alloc(php_stream_ops *ops, void *abstract, int pe
        ret->ops = ops;
        ret->abstract = abstract;
        ret->is_persistent = persistent;
-
+       ret->rsrc_id = ZEND_REGISTER_RESOURCE(NULL, ret, php_file_le_stream());
        strlcpy(ret->mode, mode, sizeof(ret->mode));
 
        return ret;
@@ -89,6 +91,15 @@ PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC) /*
 {
        int ret = 1;
 
+       if (stream->in_free)
+               return 1;
+
+       stream->in_free++;
+
+       if ((close_options & PHP_STREAM_FREE_RSRC_DTOR) == 0) {
+               /* Remove entry from the resource list */
+               zend_list_delete(stream->rsrc_id);
+       }
        if (close_options & PHP_STREAM_FREE_CALL_DTOR) {
                if (stream->fclose_stdiocast == PHP_STREAM_FCLOSE_FOPENCOOKIE) {
                        /* calling fclose on an fopencookied stream will ultimately
@@ -98,6 +109,7 @@ PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC) /*
                                php_stream_free.
                                Lets let the cookie code clean it all up.
                         */
+                       stream->in_free = 0;
                        return fclose(stream->stdiocast);
                }
 
@@ -125,6 +137,21 @@ PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC) /*
                        stream->wrapperdata = NULL;
                }
 
+#if ZEND_DEBUG
+               if ((close_options & PHP_STREAM_FREE_RSRC_DTOR) && (stream->__exposed == 0) && (EG(error_reporting) & E_WARNING)) {
+                       /* it leaked: Lets deliberately NOT pefree it so that the memory manager shows it
+                        * as leaked; it will log a warning, but lets help it out and display what kind
+                        * of stream it was. */
+                       char leakbuf[512];
+                       snprintf(leakbuf, sizeof(leakbuf), __FILE__ "(%d) : Stream of type '%s' 0x%08X was not closed\n", __LINE__, stream->ops->label, (unsigned int)stream);
+# if defined(PHP_WIN32)
+                       OutputDebugString(leakbuf);
+# else
+                       fprintf(stderr, leakbuf);
+# endif
+               }
+               else
+#endif
                pefree(stream, stream->is_persistent);
        }
 
@@ -619,8 +646,10 @@ php_stream_ops     php_stream_stdio_ops = {
        php_stdiop_gets, php_stdiop_cast,
        "STDIO"
 };
+/* }}} */
 
-PHPAPI php_stream *_php_stream_fopen_with_path(char *filename, char *mode, char *path, char **opened_path STREAMS_DC TSRMLS_DC) /* {{{ */
+/* {{{ php_stream_fopen_with_path */
+PHPAPI php_stream *_php_stream_fopen_with_path(char *filename, char *mode, char *path, char **opened_path STREAMS_DC TSRMLS_DC)
 {
        /* code ripped off from fopen_wrappers.c */
        char *pathbuf, *ptr, *end;
@@ -737,6 +766,7 @@ PHPAPI php_stream *_php_stream_fopen_with_path(char *filename, char *mode, char
 }
 /* }}} */
 
+/* {{{ php_stream_fopen */
 PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, char **opened_path STREAMS_DC TSRMLS_DC)
 {
        FILE *fp;
@@ -811,7 +841,8 @@ static COOKIE_IO_FUNCTIONS_T stream_cookie_functions =
 #endif
 /* }}} */
 
-PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show_err TSRMLS_DC) /* {{{ */
+/* {{{ php_stream_cast */
+PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show_err TSRMLS_DC)
 {
        int flags = castas & PHP_STREAM_CAST_MASK;
        castas &= ~PHP_STREAM_CAST_MASK;
@@ -902,8 +933,10 @@ exit_success:
 
        return SUCCESS;
 
-} /* }}} */
+}
+/* }}} */
 
+/* {{{ wrapper init and registration */
 int php_init_stream_wrappers(TSRMLS_D)
 {
        if (PG(allow_url_fopen)) {
@@ -935,7 +968,9 @@ PHPAPI int php_unregister_url_stream_wrapper(char *protocol TSRMLS_DC)
        }
        return SUCCESS;
 }
+/* }}} */
 
+/* {{{ php_stream_open_url */
 static php_stream *php_stream_open_url(char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC)
 {
        php_stream_wrapper *wrapper;
@@ -977,7 +1012,9 @@ static php_stream *php_stream_open_url(char *path, char *mode, int options, char
        }
        return NULL;
 }
+/* }}} */
 
+/* {{{ php_stream_open_wrapper */
 PHPAPI php_stream *_php_stream_open_wrapper(char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC)
 {
        php_stream *stream = NULL;
@@ -1034,13 +1071,15 @@ out:
        }
        return stream;
 }
+/* }}} */
 
+/* {{{ php_stream_open_wrapper_as_file */
 PHPAPI FILE * _php_stream_open_wrapper_as_file(char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC)
 {
        FILE *fp = NULL;
        php_stream *stream = NULL;
 
-       stream = php_stream_open_wrapper(path, mode, options, opened_path);
+       stream = php_stream_open_wrapper_rel(path, mode, options, opened_path);
 
        if (stream == NULL)
                return NULL;
@@ -1055,9 +1094,9 @@ PHPAPI FILE * _php_stream_open_wrapper_as_file(char *path, char *mode, int optio
        }
        return fp;
 }
+/* }}} */
 
-#define PHP_STREAM_MAX_MEM     2 * 1024 * 1024
-
+/* {{{ php_stream_make_seekable */
 PHPAPI int _php_stream_make_seekable(php_stream *origstream, php_stream **newstream, int flags STREAMS_DC TSRMLS_DC)
 {
        assert(newstream != NULL);
@@ -1090,6 +1129,7 @@ PHPAPI int _php_stream_make_seekable(php_stream *origstream, php_stream **newstr
        
        return PHP_STREAM_RELEASED;
 }
+/* }}} */
 
 /*
  * Local variables:
index 898ad5e09962f7fe87720de92ea412db24eac75e..ab90e1cd3b7b600d468504519a17482e75f5150a 100644 (file)
@@ -115,7 +115,7 @@ static php_stream *user_wrapper_factory(char *filename, char *mode, int options,
        zval **args[4]; 
        int call_result;
        php_stream *stream = NULL;
-       
+
        us = emalloc(sizeof(*us));
        us->wrapper = uwrap;