Avoid double-freeing streams.

This can happen because all streams are registered as resources;
the engine also tracks them in the open_files global.

Avoid the potential for double-freeing by simply making streams exposed to the
engine have no closer for the engine to call; they will already be in the
resource list, and thus will be shut down properly at request end.
This commit is contained in:
Wez Furlong 2005-06-06 01:51:48 +00:00
parent fc8aace243
commit 42ada22e0c
2 changed files with 9 additions and 2 deletions

View File

@ -244,7 +244,9 @@ ZEND_API void zend_file_handle_dtor(zend_file_handle *fh)
fclose(fh->handle.fp); fclose(fh->handle.fp);
break; break;
case ZEND_HANDLE_STREAM: case ZEND_HANDLE_STREAM:
fh->handle.stream.closer(fh->handle.stream.handle TSRMLS_CC); if (fh->handle.stream.closer) {
fh->handle.stream.closer(fh->handle.stream.handle TSRMLS_CC);
}
break; break;
case ZEND_HANDLE_FILENAME: case ZEND_HANDLE_FILENAME:
/* We're only supposed to get here when destructing the used_files hash, /* We're only supposed to get here when destructing the used_files hash,

View File

@ -857,9 +857,14 @@ static int php_stream_open_for_zend(const char *filename, zend_file_handle *hand
handle->free_filename = 0; handle->free_filename = 0;
handle->handle.stream.handle = stream; handle->handle.stream.handle = stream;
handle->handle.stream.reader = (zend_stream_reader_t)_php_stream_read; handle->handle.stream.reader = (zend_stream_reader_t)_php_stream_read;
handle->handle.stream.closer = stream_closer_for_zend; /* don't set this; all streams are tracked as part of the resource system,
* and we'll end up double-free'ing them if we allow zend to close them
* down after the resource list has been cleaned up */
handle->handle.stream.closer = NULL; /* stream_closer_for_zend; */
handle->handle.stream.fteller = stream_fteller_for_zend; handle->handle.stream.fteller = stream_fteller_for_zend;
handle->handle.stream.interactive = 0; handle->handle.stream.interactive = 0;
/* suppress warning if this stream is not explicitly closed */
php_stream_auto_cleanup(stream);
return SUCCESS; return SUCCESS;
} }